Answer the question
In order to leave comments, you need to log in
Correct use of channels (effective go)?
I read Effective Go, channel section. Here's what I don't understand, there is code:
var sem = make(chan int, MaxOutstanding)
func handle(r *Request) {
sem <- 1 // Wait for active queue to drain.
process(r) // May take a long time.
<-sem // Done; enable next request to run.
}
func Serve(queue chan *Request) {
for {
req := <-queue
go handle(req) // Don't wait for handle to finish.
}
}
This design has problems: Serve creates a new goroutine for each incoming request, and no more than MaxOutstanding will be running at one time. If the number of requests increases too quickly, then as a result, the program may require an infinite amount of resources..
We can solve this by changing Serve using changes in the number of spawned goroutines. Here's the obvious solution, but be careful as it has a bug that we'll fix later:
func Serve(queue chan *Request) {
for req := range queue {
sem <- 1
go func() {
process(req) // Buggy; see explanation below.
<-sem
}()
}
}
The bug is that in the Go language the for loop, the variable loop is reused for each iteration, so the req variables are shared across all goroutines. This is not what we want. We need to make sure req is unique for each goroutine. Here is one way to pass the value of req as an argument to close the goroutine:
func Serve(queue chan *Request) {
for req := range queue {
sem <- 1
go func(req *Request) {
process(req)
<-sem
}(req)
}
}
Answer the question
In order to leave comments, you need to log in
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question