golang 切片 接口_Golang语言常用关键字之 make 和 new
上一章中對于golang的語言基礎(chǔ)說明如下:
- 1 函數(shù)調(diào)用
- 2 接口
- 3 反射
接下來我們來對golang的常用關(guān)鍵字進行說明,主要內(nèi)容有:
- 1. for 和 range
- 2. select
- 3. defer
- 4. panic 和 recover
- 5. make 和 new
— — — — — — — — — — — — — — — — — — — — — — — — — — — —
當(dāng)我們想要在 Go 語言中初始化一個結(jié)構(gòu)時,可能會用到兩個不同的關(guān)鍵字 — make 和 new。因為它們的功能相似,所以初學(xué)者可能會對這兩個關(guān)鍵字的作用感到困惑1,但是它們兩者能夠初始化的卻有較大的不同。
- make 的作用是初始化內(nèi)置的數(shù)據(jù)結(jié)構(gòu),也就是我們在前面提到的切片、哈希表和 Channel2;
- new 的作用是根據(jù)傳入的類型分配一片內(nèi)存空間并返回指向這片內(nèi)存空間的指針3;
我們在代碼中往往都會使用如下所示的語句初始化這三類基本類型,這三個語句分別返回了不同類型的數(shù)據(jù)結(jié)構(gòu):
slice := make([]int, 0, 100) hash := make(map[int]bool, 10) ch := make(chan int, 5)相比與復(fù)雜的 make 關(guān)鍵字,new 的功能就很簡單了,它只能接收一個類型作為參數(shù)然后返回一個指向該類型的指針:
i := new(int)var v int i := &v上述代碼片段中的兩種不同初始化方法是等價的,它們都會創(chuàng)建一個指向 int 零值的指針。
圖 - make 和 new 初始化的類型接下來我們將分別介紹 make 和 new 在初始化不同數(shù)據(jù)結(jié)構(gòu)時的過程,我們會從編譯期間和運行時兩個不同階段理解這兩個關(guān)鍵字的原理,不過由于前面的章節(jié)已經(jīng)詳細地分析過 make 的原理,所以這里會將重點放在另一個關(guān)鍵字 new 上。
1. make
在前面的章節(jié)中我們已經(jīng)談到過 make 在創(chuàng)建切片、哈希表和 Channel 的具體過程,所以在這一小節(jié),我們只是會簡單提及 make 相關(guān)的數(shù)據(jù)結(jié)構(gòu)的初始化原理。
圖 - make 關(guān)鍵字的類型檢查在編譯期間的類型檢查階段,Go 語言就將代表 make 關(guān)鍵字的 OMAKE 節(jié)點根據(jù)參數(shù)類型的不同轉(zhuǎn)換成了 OMAKESLICE、OMAKEMAP 和 OMAKECHAN 三種不同類型的節(jié)點,這些節(jié)點會調(diào)用不同的運行時函數(shù)來初始化相應(yīng)的數(shù)據(jù)結(jié)構(gòu)。
2. new
編譯器會在中間代碼生成階段通過以下兩個函數(shù)處理該關(guān)鍵字:
需要注意的是,無論是直接使用 new,還是使用 var 初始化變量,它們在編譯器看來就是 ONEWOBJ 和 ODCL 節(jié)點。這些節(jié)點在這一階段都會被 cmd/compile/internal/gc.walkstmt 轉(zhuǎn)換成通過 runtime.newobject 函數(shù)在堆上申請內(nèi)存:
func walkstmt(n *Node) *Node {switch n.Op {case ODCL:v := n.Leftif 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())}} }不過這也不是絕對的,如果通過 var 或者 new 創(chuàng)建的變量不需要在當(dāng)前作用域外生存,例如不用作為返回值返回給調(diào)用方,那么就不需要初始化在堆上。
runtime.newobject 函數(shù)會是獲取傳入類型占用空間的大小,調(diào)用 runtime.mallocgc 在堆上申請一片內(nèi)存空間并返回指向這片內(nèi)存空間的指針:
func newobject(typ *_type) unsafe.Pointer {return mallocgc(typ.size, typ, true) }runtime.mallocgc 函數(shù)的實現(xiàn)大概有 200 多行代碼,我們會在后面的章節(jié)中詳細分析 Go 語言的內(nèi)存管理機制。
3. 小結(jié)
到了最后,簡單總結(jié)一下 Go 語言中 make 和 new 關(guān)鍵字的實現(xiàn)原理,make 關(guān)鍵字的作用是創(chuàng)建切片、哈希表和 Channel 等內(nèi)置的數(shù)據(jù)結(jié)構(gòu),而 new 的作用是為類型申請一片內(nèi)存空間,并返回指向這片內(nèi)存的指針。
全套教程點擊下方鏈接直達:
IT實戰(zhàn):Go語言設(shè)計與實現(xiàn)自學(xué)教程?zhuanlan.zhihu.com總結(jié)
以上是生活随笔為你收集整理的golang 切片 接口_Golang语言常用关键字之 make 和 new的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: “黑色星期五”期间亚马逊在欧洲多地遭遇罢
- 下一篇: threejs 加载两个场景_three