New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
proposal: Go 2: nonblocking channel operators #43209
Comments
I can't say I agree with this proposal; the new syntax seems a bit cryptic, and people would have to know both ways to write the same behavior. Worse even, projects would have to choose which they prefer, and then consistently use that. I think it's best if, in general, there's just one way to write a simple operation in Go. I think syntactic sugar is only really warranted for very common patterns, like error handling or being able to add an "init" statement to |
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
This comment has been minimized.
The rest of what you say is reasonable, but there are already two ways of doing blocking channel operations: inside and outside of It could be said that blocking operations are the common case and deserve their own syntax, but in my experience nonblocking operations is more common. I am curious as to how others deal with blocking channel operations as well. There are some papers trying to deal with the problem of deadlocked programs due to channels http://mrg.doc.ic.ac.uk/publications/a-static-verification-framework-for-message-passing-in-go-using-behavioural-types/draft.pdf |
This actually used to be a thing, way back before Go 1. If I remember right, a two-variable receive assignment, like All of that being said, if this is really something that you want to abstract away because, admittedly, it takes four lines to do a relatively straightforward operation, I think that generics is probably a much better way to do it: package chans
func TryRecv[T any](c <-chan T) (v T, ok bool) {
select {
case v = <-c:
ok = true
default:
}
return v, ok
}
func TrySend[T any](c chan<- T, v T) (ok bool) {
select {
case c <- v:
ok = true
default:
}
return ok
} |
I agree with @DeedleFake that we should see if we can do with generics, if generics get added to the language. If we can, no need for the additional syntax. |
The generics solution is a reasonable compromise, thanks! |
OK, closing this issue. Thanks. |
Proposal:
Add a short syntax for non-blocking channel operations. Something like
Currently I achieve this with the following
and
This is similar in spirit to another proposal for safely extracting fields from an object: #42847, but maybe this proposal will have better luck :). If there is another proposal on a similar idea to the one being proposed here please close this one. This proposal is a small quality of life improvement.
Rationale:
Using channels without taking care of the possibility that they may block has a high chance of causing the entire program to become blocked due to a number of issues such as cycles between go routines that use channels to communicate and other traditional blocking behaviors (like reading user input) that prevent go routines from making progress.
To deal with these issues I mostly use buffered channels with channel operations that are allowed to fail: either because the channel is empty so receive fails, or because the channel is full so emit fails. In the situations where channel operations are allowed to fail my code is designed to either retry the operation at a later time or to just give up and wait for the next channel operation. For example, streaming a series of user inputs would drop some input if the system becomes severely overloaded.
I write the
select { case x <-y: default: }
code phrase so often I would appreciate having syntactic sugar for it, and maybe others would too.Language template:
Would you consider yourself a novice, intermediate, or experienced Go programmer?
Experienced
What other languages do you have experience with?
C, C++, Java, Ruby, Swift, Scheme, Python, a sprinkling of Rust and Haskell
Would this change make Go easier or harder to learn, and why?
I think it would be easier to explain the semantics of the
<-?
operator and how it expands to the largerselect{ case ... }
than the other way.Has this idea, or one like it, been proposed before?
I'm not sure.
Who does this proposal help, and why?
Go programmers that use buffered channels extensively, because it will reduce some syntactic effort needed.
Please describe as precisely as possible the change to the language.
I believe
x <-? y
can be correctly translated intoand
y = <-? x
intoWhat would change in the language spec?
If this proposal has merit I can dive deeper into this question but likely at a minimum adding a lexeme for
<-?
and a definition of the<-?
operator in the channel part of the spec.Please also describe the change informally, as in a class teaching Go.
This change allows a programmer to specify that a channel operation will not block in a succinct way.
Is this change backward compatible?
Yes
Show example code before and after the change.
Before:
After
What is the cost of this proposal? (Every language change has a cost).
The addition of another operator, and possibly the mental overhead of knowing the translation from the
<-?
operator into the more generalselect { ... }
How many tools (such as vet, gopls, gofmt, goimports, etc.) would be affected?
gofmt would need minimal changes if the AST changes at all, vet might possibly need some changes.
What is the compile time cost?
A local AST transformation, which is very low cost.
What is the run time cost?
0
Can you describe a possible implementation?
Modify the lexer and parser -- should be straight forward.
Do you have a prototype? (This is not required.)
No
How would the language spec change?
https://golang.org/ref/spec#Receive_operator and https://golang.org/ref/spec#Send_statements would need to account for the
<-?
operatorOrthogonality: how does this change interact or overlap with existing features?
It reuses the existing
select
feature.Is the goal of this change a performance improvement?
No
Does this affect error handling?
No.
Is this about generics?
No
The text was updated successfully, but these errors were encountered: