Go函数无法直接修改传入的普通变量,因所有参数均为值传递;要修改外部变量需传指针并在函数内解引用赋值,如increment(&a)使a从42变为43。

Go 中函数不能直接修改传入的普通变量
Go 语言所有参数都是值传递,包括 int、string、struct 等类型。即使你在函数内对形参赋新值,也不会影响调用方的原始变量。
用指针参数才能修改外部变量的值
要让函数“修改外部变量”,必须传入该变量的地址(即指针),并在函数内通过解引用操作符 * 修改其指向的内存内容。
- 声明指针参数:形如
func modify(x *int) - 调用时取地址:用
&v获取变量v的地址 - 函数内修改:用
*x = 新值写入目标内存位置
package main
import "fmt"
func increment(x *int) {
*x = *x + 1
}
func main() {
a := 42
fmt.Println("before:", a) // 42
increment(&a)
fmt.Println("after: ", a) // 43
}
常见错误:传指针但没解引用,或解引用了 nil 指针
两种典型翻车场景:
- 写了
x = &newVal—— 这只是改了形参指针本身,不影响外部变量 - 传了
nil指针然后执行*x = ...—— 触发 panic: "invalid memory address or nil pointer dereference" - 误以为
func f(s []int)能修改底层数组长度 —— 实际上 slice header 是值传递,append后若扩容会生成新 header,原变量不变
结构体字段修改也依赖指针接收者
如果想在方法中修改结构体字段,接收者必须是指针类型;否则方法操作的是结构体副本。
立即学习“go语言免费学习笔记(深入)”;
type Counter struct {
Value int
}
func (c *Counter) Add(n int) {
c.Value += n // ✅ 可修改原始实例
}
func (c Counter) Reset() {
c.Value = 0 // ❌ 只清零副本,原实例不变
}
调用 counter.Add(5) 有效;而 counter.Reset() 不会改变 counter.Value。
指针操作的关键不是“语法多酷”,而是明确你是否真的需要写入原始内存 —— 如果不确定,先检查变量生命周期和并发访问需求,避免意外共享状态。










