Go切片是值传递还是引用传递?

Go没有引用传递和引用类型!!!

很多人有个误区,认为涉及Go切片的参数是引用传递,或者经常听到Go切片是引用类型这种说法,今天我们就来说一下方面的问题。

什么是值传递?

将实参的值传递给形参,形参是实参的一份拷贝,实参和形参的内存地址不同。函数内对形参值内容的修改,是否会影响实参的值内容,取决于参数的本身

什么是引用传递?

将实参的地址传递给形参,函数内对形参值内容的修改,将会影响实参的值内容。Go语言是没有引用传递的,在C++中,函数参数的传递方式有引用传递。


版权声明:本文为CSDN博主「走,我们去吹风」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:https://blog.csdn.net/weixin_51991615/article/details/130345352

首先明确几个点:

  • 1、官方明确表明:Go中没有引用类型,链接在这
  • 2、官方明确表明:Go中function所有参数的传递都是值传递,链接在这
  • 3、Golang默认是值传递,即拷贝传递;
  • 4、有些值头部head中含有地址,如(切片,map类型),所以导致看起来像是引用传递

那么问题来了,既然Go没有引用类型的说法,且function的参数都是值传递,为什么当我使用切片slice或者map等类型作为参数时,有传引用的错觉呢?

复制代码
/**
 * 测试切片不是引用传递
 */
func TestPassByValue(t *testing.T) {
	sli := []int{0, 1, 2, 3, 4}
	fmt.Printf("sli的地址:%p\n", unsafe.Pointer(&sli))
	fmt.Printf("sli[0]的地址:%p\n", unsafe.Pointer(&sli[0])) 
	//unsafe.Pointer(&sli[0])是一个指针不假,但它也仅仅是切片结构内包含的一个值
	t.Log(sli)
	modifySlice(sli)
	t.Log(sli)
}
func modifySlice(s []int) {
	//slice的底层大概如下:
	type slice struct {
		array unsafe.Pointer   // 就是这里的unsafe.Pointer(&s[0]),因为是值传递,所以这个指针是跟外面一样的
		len int
		cap int
	}
	fmt.Printf("参数的地址:%p\n", unsafe.Pointer(&s))
	fmt.Printf("参数[0]的地址: %p \n", unsafe.Pointer(&s[0]))
	s[0] = 111 //此时直接修改参数的值,外面的值也跟着同步修改
	s[1] = 222 //但当你进行append操作或者二倍扩容时,&s[0]的地址就会改变,数外的切片就不会跟着改变了。
}

总结

之所以有传引用的错觉是因为slice本质是一个结构体,结构体内有个指针值,而这个值指向切片的第一个元素,因为是值传递,所以slice内的这个指针跟函数外边是一样的,此时,你在函数内修改切片的某个值,函数外会跟着改变。 但当你进行append操作或二倍扩容时,这个指针值就会改变,此时,你再次在函数内对切片进行修改,函数外不会跟着改变。

相关推荐
念何架构之路3 小时前
Go语言常见并发模式
开发语言·后端·golang
XMYX-04 小时前
26 - Go recover 捕获错误:优雅恢复的真正意义
开发语言·golang
XMYX-08 小时前
27 - Go string 字符串处理与格式化:从底层原理到工程实践
开发语言·golang
lolo大魔王8 小时前
Go 语言原生 SQL 操作 MySQL 超详细全解 + 生产级项目模板(纯官方库无ORM)
数据库·sql·golang
Java面试题总结1 天前
Go 里什么时候可以“panic”?
开发语言·后端·golang
吴声子夜歌2 天前
Go——并发编程
开发语言·后端·golang
geovindu2 天前
go: Lock/Mutex Pattern
开发语言·后端·设计模式·golang·互斥锁模式
码农阿豪2 天前
Go 语言操作金仓数据库(上篇):环境搭建与连接管理
开发语言·数据库·golang
码农阿豪2 天前
Go 语言操作金仓数据库(下篇):SQL 执行、类型映射与超时控制
数据库·sql·golang
~|Bernard|3 天前
五,go语言的内存管理
开发语言·后端·golang