传结构体指针才能修改原字段,因为Go函数参数是值传递,传结构体副本无法影响原变量,只有传*Struct并通过解引用才能写回原始内存。

为什么传结构体指针才能修改原字段
Go 函数参数是值传递,传 struct 本身会复制整个结构体。哪怕只改一个 int 字段,函数内操作的也是副本,原变量不受影响。只有传 *MyStruct,函数拿到的是内存地址,才能通过解引用(*)写回原始内存位置。
修改结构体字段的两种常见写法对比
假设结构体定义为:
type User struct {
Name string
Age int
}下面两种方式都能改字段,但适用场景不同:
- 直接在函数内解引用赋值:适合单次、明确字段名的操作
- 用方法接收者声明为指针:适合复用逻辑、链式调用或需要同时读写多个字段
错误示范(传值无法修改):
func updateUser(u User) {
u.Name = "Alice" // 只改了副本
}
u := User{Name: "Bob"}
updateUser(u)
fmt.Println(u.Name) // 输出 Bob,没变
正确写法(传指针):
func updateUser(u *User) {
u.Name = "Alice" // u 是指针,u.Name 等价于 (*u).Name
}
u := User{Name: "Bob"}
updateUser(&u)
fmt.Println(u.Name) // 输出 Alice
方法接收者用 *T 还是 T?看是否要改字段
如果方法里要修改接收者的字段,接收者必须是 *T。否则编译报错:cannot assign to u.Name in method expression。
-
func (u User) setName(n string):u是副本,u.Name = n不影响调用方 -
func (u *User) setName(n string):可安全修改原结构体的Name字段 - 即使结构体很大,用
*T接收者也更高效——只传 8 字节地址,而非整个结构体拷贝
容易忽略的 nil 指针解引用 panic
传入 nil 指针后直接访问字段,运行时 panic:panic: runtime error: invalid memory address or nil pointer dereference。
- 调用前检查是否为
nil:func (u *User) setName(n string) { if u == nil { return // 或 panic("User is nil") } u.Name = n } - 构造函数返回
*User时,也要避免返回未初始化的指针(如var u *User),应显式&User{...}或用new(User) - JSON 解析到结构体指针字段时,若源数据缺失该字段,对应指针字段为
nil,访问前务必判空
字段级指针(比如 Age *int)和结构体指针是两回事,别混淆。这里讨论的是“把结构体地址传进去改它自己”,不是“结构体里存了个指针字段”。
立即学习“go语言免费学习笔记(深入)”;










