Go语言(Golang)地址引用避坑

1、channel 先看以下代码:

package mainimport "fmt"func main() { ch1 := make(chan int, 3) ch2 := ch1 ch1 <- 123 ch2 <- 456 fmt.Println(ch1, ch2)//输出地址是否一样?TODO:打印结果是? fmt.Println(<-ch2, <-ch1) // ch2中的数据是:456; ch1中的数据是123;TODO:打印结果是? }

输出结果:
Go语言(Golang)地址引用避坑
文章图片

代码分析:
在以上代码中,新定义的变量ch2:=ch1 ;ch2是地址引用,ch1,ch2地址指向的是同一块数据,ch1、ch2都可以改变数据。
2、slice 看看以下代码:
package mainimport "fmt"func main() { s := make([]int, 3) s1 := s s2 := s s[0] = 123 s1[1] = 456 s2[2] = 789 fmt.Println("原始切片:", s) fmt.Println("赋值切片:", s1) fmt.Println("赋值切片:", s2) fmt.Println("切片的长度、容量为:", len(s), cap(s)) fmt.Printf("追加之前的地址:s:%p ; s1:%p; s2:%p\n",s,s1,s2) fmt.Println("====执行append操作====") s2 = append(s2, 123) fmt.Printf("追加之后的地址:s:%p ; s1:%p; s2:%p\n",s,s1,s2) fmt.Println("原始切片s:", s) fmt.Println("赋值切片s1:", s1) fmt.Println("赋值切片s2:", s2) }

输出结果:
Go语言(Golang)地址引用避坑
文章图片

代码分析:起初,s,s1,s2都指向同一块数据。所以任意一个变量修改了该块数据,其他变量查到的都是修改之后的数据。
【Go语言(Golang)地址引用避坑】指向:
s2 = append(s2, 123),会在末尾追加一个元素,由于现有s2的

cap(s)=3, len(s)=3;

在追加数据时,容量已经不够,会开辟新的内存,将现有数据s2拷贝,形成新的s2。当然在容量足够的情况下,不会开辟新的内存空间。
再来看以下代码:(容量大于append的数据数量)
package mainimport "fmt"func main() { s := make([]int, 3,6) s1 := s s2 := s s[0] = 123 s1[1] = 456 s2[2] = 789 fmt.Println("原始切片:", s) fmt.Println("赋值切片:", s1) fmt.Println("赋值切片:", s2) fmt.Println("切片的长度、容量为:", len(s), cap(s)) fmt.Printf("追加之前的地址:s:%p ; s1:%p; s2:%p\n",s,s1,s2) fmt.Println("====执行append操作====") s2 = append(s2, 123) fmt.Printf("追加之后的地址:s:%p ; s1:%p; s2:%p\n",s,s1,s2) s[0]=888 // TODO:会修改s1、s2吗 fmt.Println("原始切片s:", s) fmt.Println("赋值切片s1:", s1) fmt.Println("赋值切片s2:", s2) }

输出效果:
Go语言(Golang)地址引用避坑
文章图片

在以上代码中添加内容:
package mainimport "fmt"func main() { s := make([]int, 3,6) s1 := s s2 := s s[0] = 123 s1[1] = 456 s2[2] = 789 fmt.Println("原始切片:", s) fmt.Println("赋值切片:", s1) fmt.Println("赋值切片:", s2) fmt.Println("切片的长度、容量为:", len(s), cap(s)) fmt.Printf("追加之前的地址:s:%p ; s1:%p; s2:%p\n",s,s1,s2) fmt.Println("====执行append操作====") s2 = append(s2, 123) fmt.Printf("追加之后的地址:s:%p ; s1:%p; s2:%p\n",s,s1,s2) s[0]=888 // TODO:会修改s1、s2吗 fmt.Println("原始切片s:", s) fmt.Println("赋值切片s1:", s1) fmt.Println("赋值切片s2:", s2) fmt.Println("执行以下操作,输出结果又是什么呢?") s = append(s, 666) fmt.Println("原始切片s:", s) fmt.Println("赋值切片s1:", s1) fmt.Println("赋值切片s2:", s2) }

Go语言(Golang)地址引用避坑
文章图片

特别说明:Go语言为了节省内存空间,对于切片、map、channel、指针等地址引用的变量,会操作同一块地址对应的数据,在操作时也特别留意。

    推荐阅读