Home >Backend Development >Golang >Why Does This Go Code Print 'Three' Three Times Instead of 'One', 'Two', and 'Three'?
Goroutine Behavior: Solving the Mystery
We stumble upon a perplexing behavior in the provided Go code:
package main import ( "fmt" "time" ) type field struct { name string } func (p *field) print() { fmt.Println(p.name) } func main() { data := []field{{"one"}, {"two"}, {"three"}} for _, v := range data { go v.print() } <-time.After(1 * time.Second) }
The question arises: why does this code consistently print "three" three times, instead of displaying "one", "two", and "three" in any order?
Understanding the Issue
The crux of the issue lies in a subtle race condition caused by the use of the range variable v in the goroutine function.
When we write v.print(), we are effectively passing a pointer to the variable v, which is a reference to the current element in the range data loop. However, the loop continues to iterate, modifying the value of v.
When the goroutine executes, it happens to have the final value of v, which is "three". This produces the unexpected output of three "three"s.
Fixing the Problem: Multiple Approaches
There are several ways to resolve this issue:
1. Using a Short Variable Declaration:
Create a new variable v scoped to each iteration of the loop:
for _, v := range data { v := v // Short variable declaration to create a new `v`. go v.print() }
2. Using a Slice of Pointers:
Change the type of data to a slice of pointers and pass the individual pointers to the goroutine function:
data := []*field{{"one"}, {"two"}, {"three"}} // Note the '*' for _, v := range data { go v.print() }
3. Using the Address of Slice Element:
Take the address of each slice element and pass the pointer to the goroutine function:
data := []*field{{"one"}, {"two"}, {"three"}} // Note the '*' for i := range data { v := &data[i] go v.print() }
Conclusion
Remember that taking addresses of range variables can lead to unexpected behavior in goroutines if the loop modifies the value of the variables. By using the techniques outlined above, we can ensure that each goroutine receives a unique value and avoid data race issues.
The above is the detailed content of Why Does This Go Code Print 'Three' Three Times Instead of 'One', 'Two', and 'Three'?. For more information, please follow other related articles on the PHP Chinese website!