最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

一文告訴你大神是如何學習Go語言之make和new

 更新時間:2023年02月26日 15:47:48   作者:Draveness  
當我們想要在 Go 語言中初始化一個結構時,其實會使用到兩個完全不同的關鍵字,也就是 make 和 new,同時出現(xiàn)兩個用于『初始化』的關鍵字對于初學者來說可能會感到非常困惑,不過它們兩者有著卻完全不同的作用,本文就和大家詳細講講

當我們想要在 Go 語言中初始化一個結構時,其實會使用到兩個完全不同的關鍵字,也就是 make 和 new,同時出現(xiàn)兩個用于『初始化』的關鍵字對于初學者來說可能會感到非常困惑,不過它們兩者有著卻完全不同的作用。

在 Go 語言中,make 關鍵字的主要作用是初始化內(nèi)置的數(shù)據(jù)結構,也就是我們在前面提到的 數(shù)組和切片、哈希表 和 Channel,而當我們想要獲取指向某個類型的指針時其實可以使用 new 關鍵字,只是知道如何使用 new 的人真的比較少,我們在這一節(jié)中就會介紹 make 和 new 它們的區(qū)別以及實現(xiàn)原理。

概述

雖然 make 和 new  都是能夠用于初始化數(shù)據(jù)結構,但是它們兩者能夠初始化的結構類型卻有著較大的不同;make 在 Go 語言中只能用于初始化語言中的基本類型:

slice := make([]int, 0, 100)
hash := make(map[int]bool, 10)
ch := make(chan int, 5)

這些基本類型都是語言為我們提供的,我們在前面的章節(jié)中其實已經(jīng)介紹過了它們初始化的過程以及原理,但是在這里還是需要提醒各位讀者注意的是,這三者返回了不同類型的數(shù)據(jù)結構:

  • slice 是一個包含 datacap 和 len 的結構體;
  • hash 是一個指向 hmap 結構體的指針;
  • ch 是一個指向 hchan 結構體的指針

而另一個用于初始化數(shù)據(jù)結構的關鍵字 new 的作用其實就非常簡單了,它只是接收一個類型作為參數(shù)然后返回一個指向這個類型的指針:

i := new(int)

var v int
i := &v

上述代碼片段中的兩種不同初始化方法其實是等價的,它們都會創(chuàng)建一個指向 int 零值的指針。

到了這里我們對 Go 語言中這兩種不同關鍵字的使用也有了一定的了解:make 用于創(chuàng)建切片、哈希表和管道等內(nèi)置數(shù)據(jù)結構,new 用于分配并創(chuàng)建一個指向?qū)愋偷闹羔槨?/p>

實現(xiàn)原理

接下來我們將分別介紹 make 和 new 在初始化不同數(shù)據(jù)結構時的具體過程,我們會從編譯期間和運行時兩個不同的階段理解這兩個關鍵字的原理,不過由于前面已經(jīng)詳細地介紹過 make 的實現(xiàn)原理,所以我們會將重點放在 new 上從 Go 語言的源代碼層面分析它的實現(xiàn)。

make

在前面的章節(jié)中我們其實已經(jīng)談到過 make 在創(chuàng)建 數(shù)組和切片、哈希表 和 Channel 的具體過程,所以在這一小節(jié)中,我們也只是會簡單提及 make 相關的數(shù)據(jù)結構初始化原理。

在編譯期間的 類型檢查 階段,Go 語言其實就將代表 make 關鍵字的 OMAKE 節(jié)點根據(jù)參數(shù)類型的不同轉(zhuǎn)換成了 OMAKESLICE、OMAKEMAP 和 OMAKECHAN 三種不同類型的節(jié)點,這些節(jié)點最終也會調(diào)用不同的運行時函數(shù)來初始化數(shù)據(jù)結構。

new

內(nèi)置函數(shù) new 會在編譯期間的 SSA 代碼生成 階段經(jīng)過 callnew 函數(shù)的處理,如果請求創(chuàng)建的類型大小時 0,那么就會返回一個表示空指針的 zerobase 變量,在遇到其他情況時會將關鍵字轉(zhuǎn)換成 newobject

func callnew(t *types.Type) *Node {
    if t.NotInHeap() {
        yyerror("%v is go:notinheap; heap allocation disallowed", t)
    }
    dowidth(t)

    if t.Size() == 0 {
        z := newname(Runtimepkg.Lookup("zerobase"))
        z.SetClass(PEXTERN)
        z.Type = t
        return typecheck(nod(OADDR, z, nil), ctxExpr)
    }

    fn := syslook("newobject")
    fn = substArgTypes(fn, t)
    v := mkcall1(fn, types.NewPtr(t), nil, typename(t))
    v.SetNonNil(true)
    return v
}

需要提到的是,哪怕當前變量是使用 var 進行初始化,在這一階段可能會被轉(zhuǎn)換成 newobject 的函數(shù)調(diào)用并在堆上申請內(nèi)存:

func walkstmt(n *Node) *Node {
    switch n.Op {
    case ODCL:
        v := n.Left
        if v.Class() == PAUTOHEAP {
            if prealloc[v] == nil {
                prealloc[v] = callnew(v.Type)
            }
            nn := nod(OAS, v.Name.Param.Heapaddr, prealloc[v])
            nn.SetColas(true)
            nn = typecheck(nn, ctxStmt)
            return walkstmt(nn)
        }
    case ONEW:
        if n.Esc == EscNone {
            r := temp(n.Type.Elem())
            r = nod(OAS, r, nil)
            r = typecheck(r, ctxStmt)
            init.Append(r)
            r = nod(OADDR, r.Left, nil)
            r = typecheck(r, ctxExpr)
            n = r
        } else {
            n = callnew(n.Type.Elem())
        }
    }
}

當然這也不是絕對的,如果當前聲明的變量或者參數(shù)不需要在當前作用域外『生存』,那么其實就不會被初始化在堆上,而是會初始化在當前函數(shù)的棧中并隨著 函數(shù)調(diào)用 的結束而被銷毀。

newobject 函數(shù)的工作就是獲取傳入類型的大小并調(diào)用 mallocgc 在堆上申請一片大小合適的內(nèi)存空間并返回指向這片內(nèi)存空間的指針:

func newobject(typ *_type) unsafe.Pointer {
    return mallocgc(typ.size, typ, true)
}

mallocgc 函數(shù)的實現(xiàn)大概有 200 多行代碼,在這一節(jié)中就不展開詳細分析了,我們會在后面的章節(jié)中詳細介紹 Go 語言的內(nèi)存管理機制。

總結

到了最后,簡單總結一下 Go 語言中 make 和 new 關鍵字的實現(xiàn)原理,make 關鍵字的主要作用是創(chuàng)建切片、哈希表和 Channel 等內(nèi)置的數(shù)據(jù)結構,而 new 的主要作用是為類型申請一片內(nèi)存空間,并返回指向這片內(nèi)存的指針。

Reference

  • Allocation with new
  • Allocation with make
  • Make and new

到此這篇關于一文告訴你大神是如何學習Go語言之make和new的文章就介紹到這了,更多相關Go語言make new內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • Go中的fuzz模糊測試使用實戰(zhàn)詳解

    Go中的fuzz模糊測試使用實戰(zhàn)詳解

    這篇文章主要為大家介紹了Go中的fuzz模糊測試使用實戰(zhàn)詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • golang版本升級的簡單實現(xiàn)步驟

    golang版本升級的簡單實現(xiàn)步驟

    個人感覺Go在眾多高級語言中,是在各方面都比較高效的,下面這篇文章主要給大家介紹了關于golang版本升級的簡單實現(xiàn)步驟,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下
    2023-02-02
  • golang中的select關鍵字用法總結

    golang中的select關鍵字用法總結

    這篇文章主要介紹了golang中的select關鍵字用法總結,本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2020-06-06
  • Golang配置解析神器go?viper使用詳解

    Golang配置解析神器go?viper使用詳解

    viper是一個很完善的Go項目配置解決方案,很多著名的開源項目都在使用,比如Hugo,Docker都使用了該庫,使用viper可以讓我們專注于自己的項目代碼,而不用自己寫那些配置解析代碼,本文給大家介紹Golang配置解析神器go?viper使用,感興趣的朋友一起看看吧
    2022-05-05
  • go循環(huán)依賴的最佳解決方案

    go循環(huán)依賴的最佳解決方案

    ? import cycle not allowed(循環(huán)依賴不被允許)相信作為每一個golang語言使用研發(fā),都遇到過這個令人頭痛的報錯,循環(huán)依賴是指兩個或多個模塊之間互相依賴,形成了一個閉環(huán)的情況,本文會結合部分案例對解決方案進行講解,需要的朋友可以參考下
    2023-10-10
  • go語言beego框架web開發(fā)語法筆記示例

    go語言beego框架web開發(fā)語法筆記示例

    這篇文章主要為大家介紹了go語言beego框架web開發(fā)語法筆記示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步早日升職加薪
    2022-04-04
  • golang復制文件夾移動到另一個文件夾實現(xiàn)方法詳解

    golang復制文件夾移動到另一個文件夾實現(xiàn)方法詳解

    這篇文章主要為大家介紹了golang復制文件夾并移動到另一個文件夾實現(xiàn)方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-07-07
  • go語言面試如何實現(xiàn)自旋鎖?

    go語言面試如何實現(xiàn)自旋鎖?

    這篇文章主要為大家介紹了go語言面試中常問的如何實現(xiàn)自旋鎖問題實例解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-11-11
  • Golang TCP粘包拆包問題的解決方法

    Golang TCP粘包拆包問題的解決方法

    這篇文章主要給大家介紹了Golang TCP粘包拆包問題的解決方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用Golang具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-07-07
  • Golang 中的可測試示例函數(shù)(Example Function)詳解

    Golang 中的可測試示例函數(shù)(Example Function)詳解

    這篇文章詳細講解了 Golang 中的可測試示例函數(shù),示例函數(shù)類似于單元測試函數(shù),但沒有  *testing 類型的參數(shù),編寫示例函數(shù)也是很容易的,本文就通過代碼示例給大家介紹一下Golang的可測試示例函數(shù),需要的朋友可以參考下
    2023-07-07

最新評論

三穗县| 方山县| 平陆县| 铜山县| 即墨市| 莱阳市| 嘉定区| 盖州市| 榆中县| 桐梓县| 界首市| 乌兰浩特市| 伊金霍洛旗| 北京市| 伊吾县| 永顺县| 敦化市| 固安县| 红安县| 尉犁县| 乐陵市| 景宁| 合山市| 拜城县| 沐川县| 手游| 孙吴县| 咸丰县| 罗平县| 延庆县| 呼玛县| 枣庄市| 荣成市| 康平县| 阜阳市| 建瓯市| 江口县| 盈江县| 甘洛县| 通州区| 云林县|