首頁 > 後端開發 > Golang > 主體

為什麼go中的receiver name不推薦使用this或self

發布: 2023-07-21 13:23:26
轉載
683 人瀏覽過

在日常的開發中我們除了定義函數以外, 我們也會定義一些方法。這本來沒有什麼, 但是一些從PHP或其他物件導向語言轉GO的同學往往會把receiver name命名為thisself#, 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點:

  1. 方法接受者名稱應反映其身份,並且不要使用methisself這些物件導向語言的典型標誌符。

  2. 在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)
// 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等具有特殊含义的名称啦。

Receiver是可以为nil的!!!

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

源代码截图如下: 為什麼go中的receiver name不推薦使用this或self

惊出我一身冷汗的正是图中标红的部分,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()
}
登入後複製

上述输出如下:

為什麼go中的receiver name不推薦使用this或self

a.test()能夠正常輸出,只有在處理變數結構體內部變數v才報出panic! ! !還好本文前面已經介紹了Receiver是方法的第一個參數。正因為是第一個參數所以僅僅作為參數傳遞時即使是nil也能夠正常調用函數,而在真正使用的地方報出panic。

以上是為什麼go中的receiver name不推薦使用this或self的詳細內容。更多資訊請關注PHP中文網其他相關文章!

相關標籤:
go
來源:Go语言进阶学习
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板
關於我們 免責聲明 Sitemap
PHP中文網:公益線上PHP培訓,幫助PHP學習者快速成長!