go 语言是传值还是传引用
结论:go 语言中所有东西都是以值进行传递的。也就是说,一个函数总是得到一个被传递的东西的副本,就像有一个赋值语句将值赋给参数一样
- 向一个函数传递int 值,会得到int值的一个副本
- 传递一个指针会得到指针的副本,不会得到指针所指向的数据
- 特殊的map 和slice :他们包含指向底层map 或slice 数据的指针的描述符
- 复制一个 map 或 slice 值并不会复制它所指向的数据。
复制一个接口值会复制存储在接口值中的东西。
如果接口值持有一个结构,复制接口值就会复制该结构。如果接口值持有一个指针,复制接口值会复制该指针,但同样不会复制它所指向的数据。
所以go 语言中一切都是值传递没有引用传递
传值
传值:值传递,其指的是在调用函数时将实际参数复制一份传递到函数中,这样在函数中如果对参数进行修改,将不会影响到实际参数。复制了一份,指向的不是同一个内存地址
函数传地址的时候,是怎么做到修改到原来的参数的值的呢?
如果传过去的值是指向内存空间的地址,那么是可以对这块内存空间做修改的
也就是这两个内存地址,其实是指针的指针,其根源都指向着同一个指针,也就是指向着变量 s。因此我们进一步修改变量 s。
传引用
传引用,也叫做引用传递(pass by reference),指在调用函数时将实际参数的地址直接传递到函数中,那么在函数中对参数所进行的修改,将影响到实际参数。
在 Go 语言中,官方已经明确了没有传引用,也就是没有引用传递这一情况。
因此借用文字简单描述,像是例子中,即使你将参数传入,最终所输出的内存地址都是一样的。
map 和slice
Go 语言中的 map 和 slice 类型,能直接修改,难道不是同个内存地址,不是引用了?
“map 和 slice 的行为类似于指针,它们是包含指向底层 map 或 slice 数据的指针的描述符”
我们称其为 “引用类型”,但 “引用类型” 不等同于就是传引用,又或是引用传递了,还是有比较明确的区别的。
下一个问题是:为什么 slice 类型可以直接修改源数据的值呢。
其实和输出的原理是一样的,在 Go 语言运行时,传递的也是相应 slice 类型的底层数组的指针,但需要注意,其使用的是指针的副本。严格意义是引用类型,依旧是值传递。
总结
在今天这篇文章中,我们针对 Go 语言的日经问题:“Go 语言到底是传值(值传递),还是传引用(引用传递)” 进行了基本的讲解和分析。
另外在业内中,最多人犯迷糊的就是 slice、map、chan 等类型,都会认为是 “引用传递”,从而认为 Go 语言的 xxx 就是引用传递,我们对此也进行了案例演示。
这实则是不大对的认知,因为:“如果传过去的值是指向内存空间的地址,是可以对这块内存空间做修改的”。
其确实复制了一个副本,但他也借由各手段(其实就是传指针),达到了能修改源数据的效果,是引用类型。
石锤,Go 语言只有值传递,
参考:https://mp.weixin.qq.com/s/qsxvfiyZfRCtgTymO9LBZQ