“我明明在函数里修改了这个切片,为什么出来一看,原切片纹丝不动?”
刚学Go语言的小王对着屏幕挠头,这已经是他今天第三次被函数参数传递坑到了。旁边的高级工程师老李瞄了一眼,淡淡说了句:“Go里只有值传递,但有的值是个‘地址小纸条’。”
小王更懵了。
如果你也有过类似的困惑,别担心,今天咱们就来彻底搞懂Go函数参数传递的那些事儿。我会用最接地气的方式,让你不仅明白原理,还能在实际编码中游刃有余。
第一章:从生活比喻理解两种传递
想象一下,你要给同事一份重要文件:
值传递就像复印文件。你把文件复印一份,把复印件交给同事。同事可以在复印件上随便涂改、划线、做笔记,但你的原文件完全不受影响。安全是安全,但如果文件很大,复印起来就挺费纸费时间。
引用传递则像共享云文档。你直接把文档链接发给同事,同事点开链接,在同一个文档上修改。他加的任何批注、删除的任何内容,你这边都能实时看到。效率是高,但万一同事手滑删了重要内容,大家就一起遭殃。
Go语言在参数传递上采取了“表面老实,内心复杂”的策略:它严格来说只有值传递,但当它传递某些类型时,传递的值实际上是“数据保险箱的钥匙复印件”。
第二章:值传递 - 最安全的“复印件”
先来看看最直白的值传递。Go中的基本类型(int、float、bool、string、数组和结构体)都是实实在在的值传递。
package main
import "fmt"
// 值传递示例:基本类型
func addOne(num int) {
num = num + 1
fmt.Printf("函数内num的值:%d,地址:%p\n", num, &num)
}
// 值传递示例:数组
func modifyArray(arr [3]int) {
arr[0] = 999
fmt.Printf("函数内arr:%v,地址:%p\n", arr, &arr)
}
func main() {
// 基本类型值传递
originalNum := 10
fmt.Printf("调用前num的值:%d,地址:%p\n", originalNum, &originalNum)
addOne(originalNum)
fmt.Printf("调用后num的值:%d\n\n", originalNum)
// 数组值传递
originalArray := [3]int{1, 2, 3}
fmt.Printf("调用前arr:%v,地址:%p\n", originalArray, &originalArray)
modifyArray(originalArray)
fmt.Printf("调用后arr:%v\n", originalArray)
}
运行结果:
调用前num的值:10,地址:0xc00001a0a8
函数内

最低0.47元/天 解锁文章

被折叠的 条评论
为什么被折叠?



