
go语言中函数返回结构体等值类型时,默认传递的是副本,因此对返回值的修改不会影响原始变量;若需修改原始数据,应返回指针并通过对指针解引用进行操作。
go语言中函数返回结构体等值类型时,默认传递的是副本,因此对返回值的修改不会影响原始变量;若需修改原始数据,应返回指针并通过对指针解引用进行操作。
在Go语言中,所有参数和返回值均采用值传递(pass-by-value)机制。这意味着当函数返回一个结构体(如 Person)时,实际返回的是该结构体在内存中的完整拷贝,而非原始变量的引用。因此,对返回值的任何修改——例如 rP.Age = 40——仅作用于这个临时副本,原始包级变量 p 完全不受影响。
以下为原始代码的行为分析:
func GetPerson() Person {
return p // 返回 p 的一份深拷贝
}
func main() {
rP := GetPerson() // rP 是独立于 p 的新实例
rP.Age = 40 // 仅修改 rP,p.Age 仍为 15
fmt.Println(GetPerson()) // 再次返回 p 的新拷贝,Age 仍是 15
}输出结果为:
{Bob Rolf 15}
{Bob Rolf 15}✅ 正确做法是让 GetPerson() 返回指向 p 的指针:
立即学习“go语言免费学习笔记(深入)”;
func GetPerson() *Person {
return &p // 返回 p 的地址
}
func main() {
rP := GetPerson() // rP 是 *Person 类型,指向 p
rP.Age = 40 // 等价于 (*rP).Age = 40,直接修改 p.Age
fmt.Println(GetPerson()) // 输出 {Bob Rolf 40}
}⚠️ 注意事项:
- 使用指针虽可实现原地修改,但也带来副作用风险(多个地方意外修改共享状态);
- 若 p 是包级变量,需考虑并发安全——多 goroutine 同时读写时应加锁(如 sync.Mutex);
- 对于小型结构体(如仅含几个字段),值传递开销小且更安全;仅当明确需要共享状态或结构体较大时,才优先选用指针返回。
总结:理解 Go 的值语义是掌握其内存模型的关键——“返回什么,就得到什么的副本”;要共享可变状态,请显式使用指针。


















