Reputation:
I understand that usually, if I wish to access an out-of-scope variable from a Go routine, it is my responsibility to create a copy to be conceptually owned by the Go routine. Is this also true for channels, or are those exempt?
Effective Go #channels explains this with the words "it may seem odd to write req := req
but it's a [sic] legal and idiomatic in Go to do this," referring to this code example:
var sem = make(chan int, MaxOutstanding)
// (other code, filling sem, defining process(..), etc., omitted)
func Serve(queue chan *Request) {
for req := range queue {
<-sem
req := req // Create new instance of req for the goroutine.
go func() {
process(req)
sem <- 1
}()
}
}
I happened to have very nearly replicated this example code in my own project (except that I am using a chan struct{}
rather than chan int
for my semaphore, and declare it local to the Serve
func). Staring at it, I am wondering if accessing the same channel from multiple concurrent goroutines is really fine, or if something like sem := sem
is called for.
Upvotes: 2
Views: 1502
Reputation: 2744
Yes, there is no issue with using the same channel from multiple goroutines, it's quite normal to do so.
The reason for the req := req
is not for the benefit of the goroutine, but is instead required to prevent unexpected behavior within the closure. Without it, each iteration of the loop will change the value of req within the closure rather than giving it a unique value each time.
A quick example of this effect can be found here: http://play.golang.org/p/ylRQkh2SeC
Upvotes: 5
Reputation: 6545
Channel accesses are thread-safe, so you do not need to lock it or make local copies of it or anything like that.
Upvotes: 4