Go函数参数均为值传递,传指针(T)实为传地址副本,因副本与原指针指向同一内存,故通过x=可修改原始变量;函数签名须为*int、调用须用&val,否则编译报错。

函数参数传指针才能修改原始变量
Go 里所有参数都是值传递,哪怕你传的是一个 *int,传进去的也是这个指针的副本。但这个副本和原指针指向同一块内存,所以通过它解引用(*)赋值,就能改到外部变量。不传指针,只传 int,函数里再怎么改都只是改副本。
func modify(x *int) 这样写才有效
函数签名必须明确接收指针类型,调用时也得传地址(&)。常见错误是忘记加 &,比如写成 modify(val) 而不是 modify(&val),编译直接报错:cannot use val (type int) as type *int in argument to modify。
示例:
func modify(x *int) {
*x = 42
}
func main() {
a := 10
modify(&a)
fmt.Println(a) // 输出 42
}
结构体字段修改不用额外取地址
如果函数接收的是结构体指针(*MyStruct),那么内部可以直接用 .字段名 修改,不需要对字段再取地址或解引用。这是因为 Go 允许对结构体指针直接访问字段(语法糖),等价于 (*s).Field。
立即学习“go语言免费学习笔记(深入)”;
使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
容易踩的坑:
- 误以为要写
(*s).Name = "new"—— 可以,但s.Name = "new"更简洁且等效 - 传了结构体值(
MyStruct)而非指针,改字段只影响副本 - 字段本身是指针类型(如
name *string),那要改的是*s.name,不是s.name
nil 指针解引用会 panic
传进来的指针可能是 nil,比如调用方写了 modify(nil)。此时在函数内执行 *x = ... 会触发 panic: runtime error: invalid memory address or nil pointer dereference。
安全做法是先判空:
func modify(x *int) {
if x == nil {
return // 或返回错误、log 等
}
*x = 42
}
实际工程中,是否允许 nil 应由接口契约约定;但只要没明说可空,调用方传 nil 就属于 bug,而被调用方不做检查就直接解引用,等于把崩溃责任推给了上游。
真正麻烦的不是语法怎么写,而是想清楚:这个变量“是否本就应该被函数修改”,以及“谁负责保证指针非空”。

















