Go语言中所有参数均为值传递,但int等值类型复制全部内容,slice等引用类型仅复制header(含指针),故修改元素影响原变量;需改原始值必须传指针。
Go语言中没有传统意义上的“引用类型”,所有参数都是值传递,但不同数据类型的底层行为差异会让开发者产生“值类型”和“引用类型”的直观感受。关键在于:传递的是变量的副本,而这个副本的内容决定了它是“独立拷贝”还是“指向同一底层资源”的句柄。
包括 int、float64、bool、string、struct、array 等。它们在赋值或传参时,整个数据内容被完整复制一份。
包括 slice、map、channel、func、interface{}。它们本质是**头信息结构体(header)**,内部包含指针、长度、容量等字段,传参时只复制这个 header,而非底层数据。
s[0] = 10)会影响原 slice,因为 header 中的指针指向同一底层数组s = append(s, 1))可能扩容并生成新底层数组,此时原 slice 不受影响——因为只是改了副本 header 的指针,没动原来的make 重新赋值给参数变量,不影响外部如果你需要在函数内修改原始变量的值(比如改变 int 变量内容、替换 struct 字段、或让 slice 指向新数组),必须显式传入指针。
立即学习“go语言免费学习笔记(深入)”;
*T,调用时传 &x
*p = ... 修改原始内存位置的值以下代码清晰展示差异:
func modifyInt(x int) { x = 999 }
func modifySlice(s []int) { s[0] = 999; s = append(s, 123) }
func modifySlicePtr(s *[]int) { *s = append(*s, 456) }
func main() {
a := 10
modifyInt(a)
fmt.Println(a) // 输出 10 —— 值类型,未变
s := []int{1, 2, 3}
modifySlice(s)
fmt.Println(s) // 输出 [999 2 3] —— 元素被改,但 append 没影响原 s
modifySlicePtr(&s)
fmt.Println(s) // 输出 [999 2 3 456] —— 通过指针成功追加
}