Go语言指针问题很奇怪,原因分析及正确做法

2023-04-1909:35:34编程语言入门到精通Comments674 views字数 830阅读模式

使用Go语言经常会犯的错误。当我们遍历一个数组,如果用range获取变量保存到另一个数组或者slice时,会遇到令人困惑的问题。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/35726.html

func main() {
    slice := []int{1, 2, 3}
    var ptrSlice []*int
    for _, v := range slice {
        ptrSlice = append(ptrSlice, &v)
    }
    for _, v := range ptrSlice {
        fmt.Println(*v)
    }
}

输出:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/35726.html

3
3
3

原因分析

对于 for range 语句的实现,从编译器源码 gofrontend/go/statements.cc/For_range_statement::lower_range_slice()方法中可以看到有如下注释:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/35726.html

 // The loop we generate:
  //   for_temp := range
  //   len_temp := len(for_temp)
  //   for index_temp = 0; index_temp < len_temp; index_temp++ {
  //           value_temp = for_temp[index_temp]
  //           index = index_temp
  //           value = value_temp
  //           original body
  //   }

go代码表示如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/35726.html

sa := s
sv1 := 0
sn := len(sa)
v1 := sv1
v2 := nil
for ; sv1 < sn; sv1++ {
  tmp := sa[sv1]
  v1, v2 = sv1, tmp
}

通过上面代码可以发现,返回的永远都是v2的变量,也就是获取的是v2变量的地址,所以输出的结果都是3文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/35726.html

正确做法:

使用&slice[i]替代&v,代码如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/35726.html

func main() {
    slice := []int{1, 2, 3}
    var ptrSlice []*int
    for i, _ := range slice {
        ptrSlice = append(ptrSlice, &slice[i])
    }
    for _, v := range ptrSlice {
        fmt.Println(*v)
    }
}

作者:奇妙咖啡V0
来源:简书文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/35726.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/35726.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定