Golang

关注公众号 jb51net

关闭
首页 > 脚本专栏 > Golang > Go语言地址引用

Go语言地址引用的问题解决

作者:好易学·数据结构

本文主要介绍了Go语言中channel和slice的引用行为,它们在操作时会共享同一块数据,及在追加数据时可能开辟新内存的情况,下面就来详细的介绍一下,感兴趣的可以了解一下

1、channel

先看以下代码:

package main

import "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:打印结果是?
}

输出结果:

代码分析:

在以上代码中,新定义的变量ch2:=ch1 ;ch2是地址引用,ch1,ch2地址指向的是同一块数据,ch1、ch2都可以改变数据。

2、slice

看看以下代码:

package main

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

输出结果:

代码分析:起初,s,s1,s2都指向同一块数据。所以任意一个变量修改了该块数据,其他变量查到的都是修改之后的数据。

指向:

s2 = append(s2, 123),会在末尾追加一个元素,由于现有s2的
cap(s)=3, len(s)=3;

在追加数据时,容量已经不够,会开辟新的内存,将现有数据s2拷贝,形成新的s2。当然在容量足够的情况下,不会开辟新的内存空间。

再来看以下代码:(容量大于append的数据数量)

package main

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

输出效果:

在以上代码中添加内容:

package main

import "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语言为了节省内存空间,对于切片、map、channel、指针等地址引用的变量,会操作同一块地址对应的数据,在操作时也特别留意。

到此这篇关于Go语言地址引用的问题解决的文章就介绍到这了,更多相关Go语言地址引用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文