golang mistakes

定期更新总结应用golang过程中遇到的常见问题。

关注我,不迷路

2. 奇怪的指针

这个是应用Go语言常常会犯的谬误。当咱们遍历一个数组,如果用range获取变量保留到另一个数组或者slice时,会遇到令人困惑的问题。

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)    }}

输入:

333

起因剖析

对于 for range 语句的实现,从编译器源码 gofrontend/go/statements.cc/For_range_statement::lower_range_slice()办法中能够看到有如下正文:

 // 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代码示意如下:

sa := ssv1 := 0sn := len(sa)v1 := sv1v2 := nilfor ; sv1 < sn; sv1++ {  tmp := sa[sv1]  v1, v2 = sv1, tmp}

通过下面代码能够发现,返回的永远都是v2的变量,也就是获取的是v2变量的地址,所以输入的后果都是3

正确做法:

应用&slice[i]代替&v,代码如下:

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)    }}

本文由mdnice多平台公布