Skip to content

Commit b81d4df

Browse files
ianlancetaylorgopherbot
authored andcommitted
_content/doc/effective_go: remove discussion of loop variable reuse
It's no longer needed as of the Go 1.22 release. Fixes golang/go#68808 Change-Id: Ib968a414703d28c1d4b4c5300bb5c697264b639e Reviewed-on: https://go-review.googlesource.com/c/website/+/604575 Reviewed-by: Carlos Amedee <[email protected]> Reviewed-by: Ian Lance Taylor <[email protected]> Auto-Submit: Ian Lance Taylor <[email protected]> Reviewed-by: Rob Pike <[email protected]> LUCI-TryBot-Result: Go LUCI <[email protected]>
1 parent 31640b1 commit b81d4df

File tree

1 file changed

+5
-55
lines changed

1 file changed

+5
-55
lines changed

_content/doc/effective_go.html

Lines changed: 5 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -2870,53 +2870,12 @@ <h3 id="channels">Channels</h3>
28702870
of them can run at any moment.
28712871
As a result, the program can consume unlimited resources if the requests come in too fast.
28722872
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:
28752874
</p>
28762875

28772876
<pre>
28782877
func Serve(queue chan *Request) {
28792878
for req := range queue {
2880-
sem &lt;- 1
2881-
go func() {
2882-
process(req) // Buggy; see explanation below.
2883-
&lt;-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 &lt;- 1
2902-
go func(req *Request) {
2903-
process(req)
2904-
&lt;-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.
29202879
sem &lt;- 1
29212880
go func() {
29222881
process(req)
@@ -2926,22 +2885,13 @@ <h3 id="channels">Channels</h3>
29262885
}</pre>
29272886

29282887
<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.)
29402891
</p>
29412892

29422893
<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
29452895
number of <code>handle</code> goroutines all reading from the request
29462896
channel.
29472897
The number of goroutines limits the number of simultaneous

0 commit comments

Comments
 (0)