<code style='color: rgb(36, 41, 46); text-align: start; caret-color: rgb(36, 41, 46); box-sizing: border-box; font-family: SFMono-Regular, Consolas, "Liberation Mono", Menlo, Courier, monospace; font-size: 11.9px; padding: 0.2em 0.4em; background-color: rgba(27, 31, 35, 0.05); border-radius: 3px;'>this
, self
, me
Tunggu. Pertama, mari kita lihat penamaan standard yang disyorkan oleh GOReceiver 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
Pengecam biasa bahasa berorientasikan objek ini.
In go, penerima kaedah sebenarnya adalah parameter lain kaedah.
Poin kedua di atas mungkin tidak mudah difahami, jadi mari lihat demo di bawah:
// T ... type T int // Println ... func (t T) Println() { fmt.Println("value: %v", t) } func main() { t := T(1) t.Println() T.Println(t) // receiver作为函数的第一个参数,这个时候发生值拷贝,所以方法内部的t变量是真实t变量的一个拷贝 // 这和this的含义是不相符的 } // 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
等具有特殊含义的名称啦。
最近在研读h2_bundle.go
的时候,发现了一段特殊的代码,顿时惊出一身冷汗,姑在本文补充一下,以防止自己和各位读者踩坑。
源代码截图如下:
惊出我一身冷汗的正是图中标红的部分,receiver居然还要判断为nil!在我的潜意识里一直是这样认为的,receiver默认都是有值的,直接使用就行了。这简直颠覆我的认知,吓得我赶紧写了个demo验证一下:
type A struct { v int } func (a *A) test() { fmt.Println(a == nil) } func (a *A) testV() { fmt.Println(a.v) } func main() { var a *A a.test() a.testV() }
上述输出如下:
a.test()
能够正常输出,只有在处理变量结构体内部变量v
才报出panic!!!还好本文前面已经介绍了Receiver是方法的第一个参数
。正因为是第一个参数所以仅仅作为参数传递时即使是nil
Anda juga boleh memanggil fungsi seperti biasa dan melaporkan panik di mana ia sebenarnya digunakan.
Atas ialah kandungan terperinci Mengapakah tidak disyorkan untuk menggunakan ini atau diri sendiri untuk nama penerima dalam go?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!