-
Notifications
You must be signed in to change notification settings - Fork 18k
proposal: Go 2.0: Mechanism to bind a channel to a goroutine #25821
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
Comments
The more I think about this, the more the devilish details present themselves.
This leads me to wonder if this mechanism would be more favorable as a generic mechanism for labelling any type as "bound". Which I guess is a bigger problem which has probably been defined more eloquently in another proposal 😂 If this is the case, I hope the example I described at least becomes a useful use-case for further pondering :) |
To better illustrate my thoughts. Here is a more useful (yet still contrived) example: Say I defined a type which took and executed some other piece of functionality via receiving either a func or an interface. Let us say that those functions or the functions defined within the interface took parameters which were bound or "pinned" to their callee goroutine: type StringProducerFunc func(ch ^chan<- string)
func SendStrings(ch ^chan<- string) {
for { ch <- "words" }
}
func Do10TimesConcurrently(fn StringProducerFunc) {
ch := make(chan string)
wg.Add(10)
for i := 0; i < 10; i++ {
go func(){
defer wg.Done()
fn(ch)
}()
}
wg.Done()
close(ch)
}
func main() { Do10TimeConcurrently(SendStrings) } The do 10 times concurrently could feel safe that closing the channel |
You are proposing a kind of type qualifier. Within a function that uses a channel type with that qualifier, values of that type may not be sent to a different goroutine. But of course the channel value can be sent to a different goroutine before entering that function; channels are only useful if you can send them to other goroutines. And detecting whether a channel value is sent to another goroutine is non-trivial, as you note above. You also don't discuss whether a value of type In general Go avoids type qualifiers. We would only add a new type qualifier for a general problem encountered by many programs. This proposal seems to be for a very specific problem that most programs do not encounter. We aren't going to do this, but thanks for the suggestion. |
Thank you for the explanation. Very much appreciated :) |
A quick note I tried to see if this has been proposed already. Haven't found anything, so taking a stab at sharing my thoughts 🙇 Sorry if this has been suggested before.
Proposal
To be able to declare (most commonly when defining another functions receiving argument types) that the channel rference being passed to a function is now bound to that goroutine. This means that function could not communicate that reference outside of its own routine. i.e. it could not pass the channel to a spawned routine or pass that channel via other means, causing it to leak into another routine.
The following is a contrived example, with likely a poor user experience. But I think it captures the intent:
Here I use the caret (
^
) to signify this channel reference will become bound to the routine it is called within. I am sure there exists a clearer user-experience for this feature.Motivation
This is to aid in defining well structured code, which does not send on a closed channel.
This is a safety mechanism in the spirit of the direction of a channel e.g.
func foo(ch chan<- string)
. I would expect it to be used in the same fashion. This new compile time enforced rule can be used to uphold best practice for handing channels off to routines which will send on them.Often after constructing a channel, it is handed off to other functions. Ideally divided into some which produce and some which consume. When clearing up and ensuring all processes have finished, we often want to inform consumers via closing the channel in question and then waiting for those consumers to exit. However, before we can safely close the channel, we must first ensure that the producers will not attempt to send again. Otherwise, the subsequent send on the closed channel will panic.
One way to do this is to interrupt the producers and wait for them to return. This can be achieved via cancelling a
context.Context
and having the producers pay attention toctxt.Done()
for example. Waiting for the producing routines doesn't give the caller complete guarantee that the channel won't get sent on again however. If the producer spawned anymore routines with that channel or worse, sent that channel on another channel 😨 to another routine, then a send could occur again.A mechanism like the one described would ensure that producers could be defined to have channels which are "bound" to the goroutine they are executed within. This gives a guarantee to the invokers of the producing functions that once the function returns nothing that it touched can send on the channel again.
I would expect that (given the caret syntax above as an example again) this would often be used in conjunction with the direction syntax. e.g.
func bar(ch ^chan<- string)
which is a function which receives a send-only channel bound to the current routine.This may not be feasible, but thought I would share the idea. I am probably asking for something extremely difficult to enforce or check at compile time.
The text was updated successfully, but these errors were encountered: