Go只有值传递和指针传递,所谓“引用类型”如slice、map本质是含指针的结构体,传参仍是值传递;修改基础类型或避免大结构体拷贝等场景必须用*T。
Go 里没有“引用传递”,只有值传递和指针传递
Go 语言中不存在 C++ 那种语法层面的引用类型(&T 作为独立类型),所有函数参数都是值传递。所谓“引用类型”(如 slice、map、chan、func、*T)只是底层数据结构包含指针字段,使得它们在传参时能“看起来像”可修改原数据——但这本质仍是值传递一个含指针的结构体。
真正想修改调用方变量的值,必须显式传入指针:*T。比如想让函数改掉一个 int 变量,不传 *int 就永远改不了。
什么时候必须用 *T 传参
以下情况需传指针,否则无法影响原始变量:
- 修改基础类型(
int、string、struct等)的字段或值 - 避免大结构体拷贝(例如几百字节以上的
struct),提升性能 - 实现接口时,方法集与接收者类型强相关:带指针接收者的方法只能被
*T调用
示例:
func increment(x *int) {
*x++
}
n := 42
increment(&n) // 必须取地址;传 n 无效
// n 现在是 43
slice、map 为什么“不用指针也能改”
因为它们本身是头信息结构体,内部含指针字段: