必须用 t 而不是 t 的唯一硬性理由是函数或方法需修改调用方原始值;因 go 参数传递为值拷贝,t 才能写回原内存,且涉及接口实现、json 反序列化、可选字段语义时也必须用 *t。

什么时候必须用 *T 而不是 T
必须用指针,只有一种硬性理由:函数或方法需要修改调用方的原始值。Go 的参数传递永远是值拷贝,T 拷的是整个结构体内容,*T 拷的只是 8 字节地址——后者才能让被调代码“写回”原始内存。
常见错误现象:func reset(u User) { u.ID = 0 } 调用后 u.ID 完全没变;或者对含 []byte、map[string]int 或几十个字段的结构体频繁传值,CPU 缓存压力明显上升。
- 要修改字段、重置内部状态(比如
buf.Reset())、或调用其他指针方法时,必须用*T -
json.Unmarshal、binary.Read等需向内存写入数据的 API,参数类型强制要求*T - 实现接口时,若该接口方法定义在指针接收者上(如
io.Reader.Read),你传T就无法满足接口,编译报错cannot use … as … value in assignment: … does not implement … (… method has pointer receiver)
结构体字段里该用 *Config 还是 Config
核心看语义:是否允许“不存在”。值类型字段总有零值(""、0、nil slice),而指针可为 nil,能明确区分「未设置」和「设为空字符串/零值」。
典型场景是配置结构体:
type Server struct {
Addr string
TLS *TLSSettings // 可选,不配就 nil
}
type TLSSettings struct {
CertFile string
KeyFile string
}
如果这里用 TLSSettings 值类型,你就没法判断用户是「没配 TLS」还是「配了但两个字段都留空」;用 *TLSSettings,判 if s.TLS != nil 就行。
Go语言(Golang)1.26.0版本提供 Go 官方 Windows amd64 MSI 安装包下载入口,版本号 1.26.0,可用于旧项目维护、兼容性测试和指定版本开发环境配置。
- 需要表达可选性、延迟初始化、或与 JSON 的
"omitempty"配合时,优先*T - 嵌套结构体只要求“必须存在”,比如
type Point struct { X, Y int },直接用Point更直观、零值有意义、无 nil panic 风险 - 性能不是首要考量——小结构体用指针反而增加 GC 压力,且每次访问都要解引用
方法接收者该用 func (u User) 还是 func (u *User)
关键不是“哪个更快”,而是“是否统一”和“能否满足接口”。一旦你写了哪怕一个指针接收者方法(比如 func (u *User) SetName()),那所有方法最好都用指针接收者——否则 User 类型本身无法满足含该方法的接口,而且值接收者调用时会悄悄拷贝,行为割裂。
- 结构体字段超过 3 个,或含切片/map/大数组,建议统一用
*T接收者,避免意外的大拷贝 - 不可变类型(如
time.Time、url.URL)或纯计算型小结构体(如type RGB [3]uint8),用值接收者更自然 - 不确定时,优先指针:Go 标准库里几乎所有可变结构体(
bytes.Buffer、sync.Mutex、http.Client)都用指针接收者
函数参数传 T 还是 *T?别只看大小
很多人记“大于 8 字节用指针”,但真正该看的是:这个参数在函数里会不会被修改?改了要不要影响外面?
比如一个 16 字节的结构体:type Vec2 struct{ X, Y float64 },如果函数只是算长度 func Len(v Vec2) float64 { return math.Sqrt(v.X*v.X + v.Y*v.Y) },传值更安全、无副作用、CPU 缓存友好;但如果函数要归一化它 func Normalize(v *Vec2),那就必须指针。
- 基础类型(
int、string、bool)永远用T,复制成本忽略不计 - 小结构体(≤2 个字段,且不含引用类型)传值更清晰,也避免 nil panic
- 函数签名暴露了语义:看到
func update(*User),调用方立刻知道这函数会改数据;看到func clone(User),就知道它是纯计算
最常被忽略的一点:指针不是性能银弹。滥用 *string、*int 会让代码多出一堆 if p == nil 判空,JSON 序列化时又得处理 null,而多数时候,值类型自带零值、线程安全、无需管理生命周期——简单就是可靠。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










