出于效率考虑,我们经常使用单个变量来循环迭代器。但在循环中,每次循环迭代中都会有不同的值,有时候会导致未知的行为。

in := []int{1, 2, 3} var out []*int for _, v := range in { out = append(out, &v) } fmt.Println("Values:", *out[0], *out[1], *out[2]) fmt.Println("Addresses:", out[0], out[1], out[2])

输出

Values: 3 3 3 Addresses: 0xc000014188 0xc000014188 0xc000014188

在out这个slice中的元素都是3。

原因:在每次迭代中,v是单个变量(内存地址不变),所以每次迭代都采用新值将 v append 到 out切片中。

go语言怎么跳出循环(Go语言for循环中使用变量引用常错常问)(1)

最简单的解决方法是将循环迭代器变量赋值到新变量中:

in := []int{1, 2, 3} var out []*int for _, v := range in { v := v out = append(out, &v) } fmt.Println("Values:", *out[0], *out[1], *out[2]) fmt.Println("Addresses:", out[0], out[1], out[2])

新的输出:

Values: 1 2 3 Addresses: 0xc0000b6010 0xc0000b6018 0xc0000b6020

在 goroutine 中使用循环迭代变量也会有相同的问题。

list := []int{1, 2, 3} for _, v := range list { go func() { fmt.Printf("%d ", v) }() }

输出将是:

3 3 3

请注意,如果不使用 goroutine 运行该函数,则代码将按预期运行。

,