introduce
New learners of Go may encounter common mistakes. There are two common mistakes that need to be mentioned separately. Why do I mention them separately because they are different from other languages because of the design of GO.
References to variables are used in loops (iterations)
In GO, the variables used in the loop are the same, but are assigned different values each time the loop is iterated. This is done for efficiency. However, if not used properly, it can lead to unexpected behavior.
Here’s a chestnut:
func main(a) {
var out []*int
for i := 0; i < 3; i++ {
out = append(out, &i)
}
fmt.Println("Values:", *out[0], *out[1], *out[2])
fmt.Println("Addresses:", out[0], out[1], out[2])}Copy the code
The above code will print:
Values: 3 3 3
Addresses: 0x40e020 0x40e020 0x40e020
Copy the code
Because each time through the loop, we’re just putting the address of variable I into the out array, because variable I is the same variable, and it only gets assigned to 3 at the end of the loop.
Solution: Declare a new variable
for i := 0; i < 3; i++ {
i := i // Copy i into a new variable.
out = append(out, &i)
}
Copy the code
The results of
Values: 0 1 2
Addresses: 0x40e020 0x40e024 0x40e028
Copy the code
The same problem applies to slicing, because slicing itself is just an address
func main(a) {
var out [][]int
for _, i := range[] [1]int{{1}, {2}, {3}} {
out = append(out, i[:])
}
fmt.Println("Values:", out)
}
Copy the code
Results:
Values: [[3] [3] [3]]
Copy the code
The same problem occurs when using coroutines in loops
Use loop variables in coroutines
As programmers like to use concurrency, you might write something like this: I’m so happy that concurrency in GO is so easy.
for _, val := range values {
go func() {
fmt.Println(val)
}()
}
Copy the code
However, you may find that the output is exactly the same! Because the coroutine of Go also takes a little bit of time to run, and by the end of the loop, you might not have run any goroute, and then val is actually assigned, so you’ll see that the output is the last value
Solutions:
for _, val := range values {
go func(val interface{}) {
fmt.Println(val)
}(val)
}
Copy the code
Of course you can
for i := range valslice {
val := valslice[i]
go func(a) {
fmt.Println(val)
}()
}
Copy the code
Reference:github.com/golang/go/w…