为什么 Go 中的 Receiver Name 不推荐使用 this 或者 self
共 1926字,需浏览 4分钟
·
2020-08-28 18:30
前言
在日常的开发中我们除了定义函数以外, 我们还会定义一些方法。这本来没有什么, 但是一些从 PHP 或者其他面向对象语言转 Go 的同学往往会把 receiver name 命名为 this
, self
, me
等。
笔者在实际项目开发中也遇到类似的同学, 屡次提醒却没有效果,于是决心写下这篇文章以便好好说服这些同学。
CR 标准做法
首先我们来看一下 GO 推荐的标准命名Receiver Names
,以下内容摘抄自 https://github.com/golang/go/wiki/CodeReviewComments#receiver-names:
The name of a method's receiver should be a reflection of its identity; often a one or two letter abbreviation of its type suffices (such as "c" or "cl" for "Client"). Don't use generic names such as "me", "this" or "self", identifiers typical of object-oriented languages that gives the method a special meaning. In Go, the receiver of a method is just another parameter and therefore, should be named accordingly. ...
简单翻译总结有如下 2 点:
方法接受者名称应反映其身份, 并且不要使用 me
,this
,self
这些面向对象语言的典型标志符。在 go 中方法接受者其实就是方法的另一个参数。
Receiver 是方法的第一个参数!
上面的第二点, 可能不是很好理解,所以我们直接看下面的 demo:
// T ...
type T int
// Println ...
func (t T) Println() {
fmt.Println("value: %v", t)
}
func main() {
t := T(1)
t.Println()
T.Println(t)
}
// output:
value: 1
value: 1
通过上面的 demo, 我们知道接受者可以直接作为第一个参数传递给方法的。而t.Println()
应该就是 Go 中的一种语法糖了。
到这里可能有同学又要问了, 既然 Go 提供了这种语糖,那我们这样命名有什么问题呢?笔者先不着急解释, 我们继续看下面的 demo:
// Test ...
type Test struct {
A int
}
// SetA ...
func (t Test) SetA(a int) {
t.A = a
}
// SetA1 ...
func (t *Test) SetA1(a int) {
t.A = a
}
func main() {
t := Test{
A: 3,
}
fmt.Println("demo1:")
fmt.Println(t.A)
t.SetA(5)
fmt.Println(t.A)
t1 := Test{
A: 4,
}
fmt.Println("demo2:")
fmt.Println(t1.A)
(&t1).SetA1(6)
fmt.Println(t1.A)
}
// output:
demo1:
3
3
demo2:
4
6
看上面的 demo 我们知道, 当 receiver 不是指针时调用 SetA
其值根本没有改变。
因为 Go 中都是值传递,所以你如果对 SetA 的 receiver 的名称命名为this
, self
等,它就已经失去了本身的意义——“调用一个对象的方法就是向该对象传递一条消息”。而且对象本身的属性也并不一定会发生改变。
综上: 请各位读者在对 receiver 命名时不要再用 this
, self
等具有特殊含义的名称啦。
推荐阅读
站长 polarisxu
自己的原创文章
不限于 Go 技术
职场和创业经验
Go语言中文网
每天为你
分享 Go 知识
Go爱好者值得关注