<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 2536字,需瀏覽 6分鐘

           ·

          2022-06-06 20:59

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

          回復(fù)“Go語言”即可獲贈從入門到進(jìn)階共10本電子書

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


          前言

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

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

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

          首先我們來看一下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é)有如下2點(diǎn):

          1. 方法接受者名稱應(yīng)反映其身份, 并且不要使用me,?this,?self這些面向?qū)ο笳Z言的典型標(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

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

          到這里可能有同學(xué)又要問了, 既然Go提供了這種語法糖,那我們這樣命名有什么問題呢?筆者先不著急解釋, 我們繼續(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其值根本沒有改變。

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

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

          Receiver是可以為nil的!!!

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

          源代碼截圖如下:?

          驚出我一身冷汗的正是圖中標(biāo)紅的部分,receiver居然還要判斷為nil!在我的潛意識里一直是這樣認(rèn)為的,receiver默認(rèn)都是有值的,直接使用就行了。這簡直顛覆我的認(rèn)知,嚇得我趕緊寫了個(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)注公眾號大家一同學(xué)習(xí)進(jìn)步:

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

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

          往期精彩文章推薦:

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

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

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

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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  精品久久做| 韩国一区二区三区在线 | 亚洲AV无码乱码国产精品蜜芽 | 日韩在线第二页 | 日本人妻视频 |