<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 中沒有引用傳遞?

          共 2937字,需瀏覽 6分鐘

           ·

          2020-12-22 13:55

          點(diǎn)擊上方藍(lán)色“Go語言中文網(wǎng)”關(guān)注,每天一起學(xué) Go

          先說清楚,在 go 中沒有引用變量,所以更不存在什么引用傳值了。

          什么是引用變量

          在類 C++ 語言中,你可以聲明一個(gè)別名,給一個(gè)變量安上一個(gè)其他名字,我們把這稱為引用變量。

          #include?

          int?main()?{
          ?int?a?=?10;
          ?int?&b?=?a;
          ?int?&c?=?b;

          ?printf("%p?%p?%p\n",?&a,?&b,?&c);?//?0x7ffe114f0b14?0x7ffe114f0b14?0x7ffe114f0b14
          ?return?0;
          }

          你可以看到 a,b,c 都指向同一塊內(nèi)存地址,三者的值相同,當(dāng)你要在不同范圍內(nèi)聲明引用變量(即函數(shù)調(diào)用)時(shí),此功能很有用。

          Go 中不存在引用變量

          與 C++ 不同的是,Go 中的每一個(gè)變量都有著獨(dú)一無二的內(nèi)存地址。

          package?main

          import?"fmt"

          func?main()?{
          ?var?a,?b,?c?int
          ?fmt.Println(&a,?&b,?&c)?//?0x1040a124?0x1040a128?0x1040a12c
          }

          你不可能在 Go 程序中找到兩個(gè)變量共享一塊內(nèi)存,但是可以讓兩個(gè)變量指向同一個(gè)內(nèi)存。

          package?main

          import?"fmt"

          func?main()?{
          ?var?a?int
          ?var?b,?c?=?&a,?&a
          ?fmt.Println(b,?c)???//?0x1040a124?0x1040a124
          ?fmt.Println(&b,?&c)?//?0x1040c108?0x1040c110
          }

          在這個(gè)例子中,bc 擁有 a 的地址,但是 bc 這兩個(gè)變量卻被存儲(chǔ)在不同的內(nèi)存地址中,更改 b 的值并不會(huì)影響到 c

          mapchannel 是引用嗎

          不是,map 和 channel 都不是引用,如果他們是的話,下面這個(gè)例子就會(huì)輸出 false

          package?main

          import?"fmt"

          func?fn(m?map[int]int)?{
          ?m?=?make(map[int]int)
          }

          func?main()?{
          ?var?m?map[int]int
          ?fn(m)
          ?fmt.Println(m?==?nil)
          }

          如果是引用變量的話,main 中的 m 被傳到 fn 中,那么經(jīng)過函數(shù)的處理 m 應(yīng)該已經(jīng)被初始化了才對(duì),但是可以看出 fn 的處理對(duì) m 并沒有影響,所以 map 也不是引用。

          map 是一個(gè)指向 runtime.hmap 結(jié)構(gòu)的指針,如果你還有疑問的話,請(qǐng)繼續(xù)閱讀下去。

          map 類型是什么

          當(dāng)我們這樣聲明的時(shí)候。

          m?:=?make(map[int]int)

          編譯器將其替換為調(diào)用 map.go/makemap[1]

          //?makemap?implements?Go?map?creation?for?make(map[k]v,?hint).
          //?If?the?compiler?has?determined?that?the?map?or?the?first?bucket
          //?can?be?created?on?the?stack,?h?and/or?bucket?may?be?non-nil.
          //?If?h?!=?nil,?the?map?can?be?created?directly?in?h.
          //?If?h.buckets?!=?nil,?bucket?pointed?to?can?be?used?as?the?first?bucket.
          func?makemap(t?*maptype,?hint?int,?h?*hmap)*hmap

          可以看到,makemap 函數(shù)返回 *hmap,一個(gè)指向hmap[2]結(jié)構(gòu)的指針,我們可以從 go 源碼中看到這些,除此之外,我們還可以證明 map 值的大小和 uintptr 一樣。

          package?main
          import?(
          ?"fmt"
          ?"unsafe"
          )

          func?main()?{
          ?var?m?map[int]int
          ?var?p?uintptr
          ?fmt.Println(unsafe.Sizeof(m),?unsafe.Sizeof(p))?//?8?8?(linux/amd64)
          }

          如果 map 是指針的話,它不應(yīng)該返回 *map[key]value 嗎

          這是個(gè)好問題,為什么表達(dá)式 make(map[int]int) 返回一個(gè) map[int]int 類型的結(jié)構(gòu)?不應(yīng)該返回 *map[int]int 嗎?

          Ian Taylor 在這個(gè)回答[3]中說:

          In the very early days what we call maps now were written as pointers, so you wrote *map[int]int. We moved away from that when we realized that no one ever wrote map without writing *map.

          所以說,Go 把 *map[int]int 重命名為 map[int]int


          via: https://dave.cheney.net/2017/04/29/there-is-no-pass-by-reference-in-go

          作者:Dave Cheney[4]譯者:Jun10ng[5]校對(duì):unknwon[6]

          本文由 GCTT[7] 原創(chuàng)編譯,Go 中文網(wǎng)[8] 榮譽(yù)推出

          參考資料

          [1]

          makemap: https://golang.org/src/runtime/map.go?h=makemap%28%29

          [2]

          hmap: https://golang.org/src/runtime/map.go?h=hmap#L115

          [3]

          在這個(gè)回答: https://groups.google.com/forum/#!msg/golang-nuts/SjuhSYDITm4/jnrp7rRxDQAJ

          [4]

          Dave Cheney: https://dave.cheney.net/about

          [5]

          Jun10ng: https://github.com/Jun10ng

          [6]

          unknwon: https://github.com/unknwon

          [7]

          GCTT: https://github.com/studygolang/GCTT

          [8]

          Go 中文網(wǎng): https://studygolang.com/



          推薦閱讀


          福利

          我為大家整理了一份從入門到進(jìn)階的Go學(xué)習(xí)資料禮包,包含學(xué)習(xí)建議:入門看什么,進(jìn)階看什么。關(guān)注公眾號(hào) 「polarisxu」,回復(fù) ebook 獲取;還可以回復(fù)「進(jìn)群」,和數(shù)萬 Gopher 交流學(xué)習(xí)。

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

          手機(jī)掃一掃分享

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

          手機(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>
                  亚洲无码免费电影 | 精品人伦一区二区三区蜜桃视频 | 怡红院一区二区 | 日本黄色一级A片 | 久久精品视频6 |