1. 為什么go中的receiver name不推薦使用this或者self

        共 2536字,需瀏覽 6分鐘

         ·

        2022-06-06 20:59

        點(diǎn)擊上方“Go語(yǔ)言進(jìn)階學(xué)習(xí)”,進(jìn)行關(guān)注

        回復(fù)“Go語(yǔ)言”即可獲贈(zèng)從入門(mén)到進(jìn)階共10本電子書(shū)

        香霧云鬟濕,清輝玉臂寒。


        前言

        在日常的開(kāi)發(fā)中我們除了定義函數(shù)以外, 我們還會(huì)定義一些方法。這本來(lái)沒(méi)有什么, 但是一些從PHP或者其他面向?qū)ο笳Z(yǔ)言轉(zhuǎn)GO的同學(xué)往往會(huì)把receiver name命名為this,?self,?me等。

        筆者在實(shí)際項(xiàng)目開(kāi)發(fā)中也遇到類似的同學(xué), 屢次提醒卻沒(méi)有效果,于是決心寫(xiě)下這篇文章以便好好說(shuō)服這些同學(xué)。

        CR標(biāo)準(zhǔn)做法

        首先我們來(lái)看一下GO推薦的標(biāo)準(zhǔn)命名Receiver Names,以下內(nèi)容摘抄自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.
        ...

        簡(jiǎn)單翻譯總結(jié)有如下2點(diǎn):

        1. 方法接受者名稱應(yīng)反映其身份, 并且不要使用me,?this,?self這些面向?qū)ο笳Z(yǔ)言的典型標(biāo)志符。

        2. 在go中方法接受者其實(shí)就是方法的另一個(gè)參數(shù)。

        Receiver是方法的第一個(gè)參數(shù)!

        上面的第二點(diǎn), 可能不是很好理解,所以我們直接看下面的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作為函數(shù)的第一個(gè)參數(shù),這個(gè)時(shí)候發(fā)生值拷貝,所以方法內(nèi)部的t變量是真實(shí)t變量的一個(gè)拷貝

        // 這和this的含義是不相符的

        }
        // output:
        value: 1
        value: 1

        通過(guò)上面的demo, 我們知道接受者可以直接作為第一個(gè)參數(shù)傳遞給方法的。而t.Println()應(yīng)該就是Go中的一種語(yǔ)法糖了。

        到這里可能有同學(xué)又要問(wèn)了, 既然Go提供了這種語(yǔ)法糖,那我們這樣命名有什么問(wèn)題呢?筆者先不著急解釋, 我們繼續(xù)看下面的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我們知道, 當(dāng)receiver不是指針時(shí)調(diào)用SetA其值根本沒(méi)有改變。

        因?yàn)镚o中都是值傳遞,所以你如果對(duì)SetA的receiver的名稱命名為this,?self等,它就已經(jīng)失去了本身的意義——“調(diào)用一個(gè)對(duì)象的方法就是向該對(duì)象傳遞一條消息”。而且對(duì)象本身的屬性也并不一定會(huì)發(fā)生改變。

        綜上: 請(qǐng)各位讀者在對(duì)receiver命名時(shí)不要再用this,?self等具有特殊含義的名稱啦。

        Receiver是可以為nil的!?。?/h2>

        最近在研讀h2_bundle.go的時(shí)候,發(fā)現(xiàn)了一段特殊的代碼,頓時(shí)驚出一身冷汗,姑在本文補(bǔ)充一下,以防止自己和各位讀者踩坑。

        源代碼截圖如下:?

        驚出我一身冷汗的正是圖中標(biāo)紅的部分,receiver居然還要判斷為nil!在我的潛意識(shí)里一直是這樣認(rèn)為的,receiver默認(rèn)都是有值的,直接使用就行了。這簡(jiǎn)直顛覆我的認(rèn)知,嚇得我趕緊寫(xiě)了個(gè)demo驗(yàn)證一下:

        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()能夠正常輸出,只有在處理變量結(jié)構(gòu)體內(nèi)部變量v才報(bào)出panic!??!還好本文前面已經(jīng)介紹了Receiver是方法的第一個(gè)參數(shù)。正因?yàn)槭堑谝粋€(gè)參數(shù)所以僅僅作為參數(shù)傳遞時(shí)即使是nil也能夠正常調(diào)用函數(shù),而在真正使用的地方報(bào)出panic。

        鑒于receiver如此特殊,所以特意在本文完成之后補(bǔ)充后續(xù)內(nèi)容以時(shí)刻提醒自己和各位讀者。

        本部分于20200827日晚補(bǔ)充。

        歡迎關(guān)注公眾號(hào)大家一同學(xué)習(xí)進(jìn)步:

        最后, 祝各位事業(yè)有成!

        -------------------?End?-------------------

        往期精彩文章推薦:

        歡迎大家點(diǎn)贊,留言,轉(zhuǎn)發(fā),轉(zhuǎn)載,感謝大家的相伴與支持

        想加入Go學(xué)習(xí)群請(qǐng)?jiān)诤笈_(tái)回復(fù)【入群

        萬(wàn)水千山總是情,點(diǎn)個(gè)【在看】行不

        瀏覽 92
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
          
          

            1. 伊人7| 成人小说图片综合网 | 黄色一级大片免费 | 古代高h肉辣浪荡np轮j | 亚洲黄色在线 |