go range 的陷阱

题目来源: 北京合链

答案:

应该是一个for循环中作用域的问题

  1. src := []int{1, 2, 3, 4, 5}
  2. var dst2 []*inv
  3. for _, v := range src {
  4. dst2 = append(dst2, &v)
  5. // fmt.println(&v)
  6. }
  7. for _, p := range dst2 {
  8. fmt.Print(*p)
  9. }
  10. // 输出
  11. // 5555

为什么呢, 因为 for-range 中 循环变量的作用域的规则限制
假如取消append()后一行的注释,可以发现循环中v的变量内存地址是一样的,也可以解释为for range相当于

  1. var i int
  2. for j := 0; j < len(src); j++ {
  3. i = src[j]
  4. dst2 = append(dst2, &i)
  5. }

而不是我们想象中的

  1. for j := 0; j < len(src); j++ {
  2. dst2 = append(dst2, &src[j])
  3. }

如果要在for range中实现,我们可以改写为

  1. src := []int{1, 2, 3, 4, 5}
  2. var dst2 []*int
  3. for _, v := range src {
  4. new_v := v
  5. dst2 = append(dst2, &new_v)
  6. // fmt.println(&new_v)
  7. }
  8. for _, p := range dst2 {
  9. fmt.Print(*p)
  10. }

参考资料

https://studygolang.com/articles/22495