Mengapakah tidak disyorkan untuk menggunakan ini atau diri sendiri untuk nama penerima dalam go?

Lepaskan: 2023-07-21 13:23:26
ke hadapan
829 orang telah melayarinya

Dalam pembangunan harian, selain mentakrifkan fungsi, kami juga mentakrifkan beberapa kaedah. Ini bukan apa-apa, tetapi sesetengah pelajar yang beralih daripada PHP atau bahasa berorientasikan objek lain ke GO sering menamakan nama penerima sebagai <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;'>thisselfmeTunggu.
Penulis juga menemui pelajar yang serupa dalam pembangunan projek sebenar Selepas peringatan berulang kali tetapi tidak berjaya, saya memutuskan untuk menulis artikel ini untuk memujuk pelajar ini.

Amalan Standard CR

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&#39;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&#39;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.
...
Salin selepas log masuk

简单翻译总结有如下2点:

  1. 方法接受者名称应反映其身份, 并且不要使用me, this, selfPengecam biasa bahasa berorientasikan objek ini.

  2. In go, penerima kaedah sebenarnya adalah parameter lain kaedah.

Penerima ialah parameter pertama 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
Salin selepas log masuk

通过上面的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
Salin selepas log masuk

看上面的demo我们知道, 当receiver不是指针时调用SetA其值根本没有改变。

因为Go中都是值传递,所以你如果对SetA的receiver的名称命名为this, self等,它就已经失去了本身的意义——“调用一个对象的方法就是向该对象传递一条消息”。而且对象本身的属性也并不一定会发生改变。

综上: 请各位读者在对receiver命名时不要再用this, self等具有特殊含义的名称啦。

Receiver是可以为nil的!!!

最近在研读h2_bundle.go的时候,发现了一段特殊的代码,顿时惊出一身冷汗,姑在本文补充一下,以防止自己和各位读者踩坑。

源代码截图如下: Mengapakah tidak disyorkan untuk menggunakan ini atau diri sendiri untuk nama penerima dalam 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()
}
Salin selepas log masuk

上述输出如下:

Mengapakah tidak disyorkan untuk menggunakan ini atau diri sendiri untuk nama penerima dalam go?

a.test()能够正常输出,只有在处理变量结构体内部变量v才报出panic!!!还好本文前面已经介绍了Receiver是方法的第一个参数。正因为是第一个参数所以仅仅作为参数传递时即使是nilAnda 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!

Label berkaitan:
go
sumber:Go语言进阶学习
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan