Go 方法接收者用值还是指针,我通常先看这三个信号
· 阅读需 2 分钟
Go 里的方法接收者,看起来是一个很小的语法点,但一旦项目写久了,你会发现它会直接影响代码语义。很多人会背口诀:能不用指针就不用指针,或者一旦要改值就用指针。可真正到工程里,光背口诀还是不够。
我后来更习惯先看三个信号,再决定这类方法该怎么写。
信号一:这个对象大不大
如果结构体本身比较大,频繁值拷贝会带来额外成本,这时候指针接收者通常更自然。
不是因为值接收者不能用,而是因为你已经能明显预见到复制开销和调用语义都会开始变重。
信号二:方法是不是在表达“修改状态”
如果一个方法本来就代表对象状态变化,比如累加、更新、重置、懒加载,那我更倾向直接用指针接收者。
因为这不仅是技术实现,也是语义表达:调用这个方法之后,对象本身会变。
反过来,如果方法更像一个纯读取、纯计算或格式化输出,值接收者往往更容易让人理解它没有副作用。
信号三:你想给这个类型暴露怎样的方法集合
这是很多人一开始不太重视,但我后来很在意的一点。
同一个类型如果一部分方法用值接收者,一部分方法用指针接收者,调用和接口适配时就会出现额外心智负担。
所以我更喜欢在一个类型内部尽量保持一致,除非确实有非常明确的语义差异。
我不太喜欢的写法
最让我别扭的是那种“明明方法不会改状态,却因为习惯全部上指针”的写法。
这样当然也能工作,但类型的语义会越来越模糊。代码读久了,你会分不清这是因为真的要共享状态,还是只是作者没想过。
小结
Go 的好处之一,是很多设计选择都能回到非常朴素的判断上。值还是指针,不一定非要争出一个绝对标准。
只要先看对象大小、状态语义和方法集合这三个信号,选择通常就不会太离谱。对我来说,这比死记硬背一条口诀更稳。
