@@ -2870,53 +2870,12 @@ <h3 id="channels">Channels</h3>
2870
2870
of them can run at any moment.
2871
2871
As a result, the program can consume unlimited resources if the requests come in too fast.
2872
2872
We can address that deficiency by changing < code > Serve</ code > to
2873
- gate the creation of the goroutines.
2874
- Here's an obvious solution, but beware it has a bug we'll fix subsequently:
2873
+ gate the creation of the goroutines:
2875
2874
</ p >
2876
2875
2877
2876
< pre >
2878
2877
func Serve(queue chan *Request) {
2879
2878
for req := range queue {
2880
- sem <- 1
2881
- go func() {
2882
- process(req) // Buggy; see explanation below.
2883
- <-sem
2884
- }()
2885
- }
2886
- }</ pre >
2887
-
2888
- < p >
2889
- The bug is that in a Go < code > for</ code > loop, the loop variable
2890
- is reused for each iteration, so the < code > req</ code >
2891
- variable is shared across all goroutines.
2892
- That's not what we want.
2893
- We need to make sure that < code > req</ code > is unique for each goroutine.
2894
- Here's one way to do that, passing the value of < code > req</ code > as an argument
2895
- to the closure in the goroutine:
2896
- </ p >
2897
-
2898
- < pre >
2899
- func Serve(queue chan *Request) {
2900
- for req := range queue {
2901
- sem <- 1
2902
- go func(req *Request) {
2903
- process(req)
2904
- <-sem
2905
- }(req)
2906
- }
2907
- }</ pre >
2908
-
2909
- < p >
2910
- Compare this version with the previous to see the difference in how
2911
- the closure is declared and run.
2912
- Another solution is just to create a new variable with the same
2913
- name, as in this example:
2914
- </ p >
2915
-
2916
- < pre >
2917
- func Serve(queue chan *Request) {
2918
- for req := range queue {
2919
- req := req // Create new instance of req for the goroutine.
2920
2879
sem <- 1
2921
2880
go func() {
2922
2881
process(req)
@@ -2926,22 +2885,13 @@ <h3 id="channels">Channels</h3>
2926
2885
}</ pre >
2927
2886
2928
2887
< p >
2929
- It may seem odd to write
2930
- </ p >
2931
-
2932
- < pre >
2933
- req := req
2934
- </ pre >
2935
-
2936
- < p >
2937
- but it's legal and idiomatic in Go to do this.
2938
- You get a fresh version of the variable with the same name, deliberately
2939
- shadowing the loop variable locally but unique to each goroutine.
2888
+ (Note that in Go versions before 1.22 this code has a bug: the loop
2889
+ variable is shared across all goroutines.
2890
+ See the < a href ="/wiki/LoopvarExperiment "> Go wiki</ a > for details.)
2940
2891
</ p >
2941
2892
2942
2893
< p >
2943
- Going back to the general problem of writing the server,
2944
- another approach that manages resources well is to start a fixed
2894
+ Another approach that manages resources well is to start a fixed
2945
2895
number of < code > handle</ code > goroutines all reading from the request
2946
2896
channel.
2947
2897
The number of goroutines limits the number of simultaneous
0 commit comments