溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

go語(yǔ)言中的new與make有什么區(qū)別

發(fā)布時(shí)間:2021-08-23 02:12:04 來(lái)源:億速云 閱讀:124 作者:chen 欄目:數(shù)據(jù)庫(kù)

本篇內(nèi)容主要講解“go語(yǔ)言中的new與make有什么區(qū)別”,感興趣的朋友不妨來(lái)看看。本文介紹的方法操作簡(jiǎn)單快捷,實(shí)用性強(qiáng)。下面就讓小編來(lái)帶大家學(xué)習(xí)“go語(yǔ)言中的new與make有什么區(qū)別”吧!

new() 和 make() 的區(qū)別

以下摘錄自 https://github.com/unknwon/the-way-to-go_ZH_CN/blob/master/eBook/07.2.md

二者都在堆上分配內(nèi)存,但是它們的行為不同,適用于不同的類型。

new(T) 為每個(gè)新的類型T分配一片內(nèi)存,初始化為 0 并且返回類型為*T的內(nèi)存地址:這種方法返回一個(gè)指向類型為 T,值為 0 的地址的指針,它適用于值類型如數(shù)組和結(jié)構(gòu)體;它相當(dāng)于&T{}。make(T)返回一個(gè)類型為 T 的初始值,它只適用于3種內(nèi)建的引用類型:切片、map 和 channel

換言之,new 函數(shù)分配內(nèi)存,make 函數(shù)初始化;下圖給出了區(qū)別:

我的理解,new返回一個(gè)變量的指針,但是這個(gè)指針指向空,你不可以直接對(duì)該指針進(jìn)行操作,否則會(huì)報(bào)錯(cuò),除非你將該指針指向一個(gè)該類型變量的地址。
make返回一個(gè)該類型的變量,以切片變量為例,上面提到,make適用于創(chuàng)建切片、map和channel,但new也可以創(chuàng)建

package mainimport "fmt"func main() {//使用make創(chuàng)建切片,返回的是變量本身s1 := make([]int,5,10)fmt.Printf("use make create slise type %T value %v \n",s1,s1)s1[0] = 123s1[4] = 321fmt.Printf("make s1 type %T value %v \n",s1,s1)//# 使用new 創(chuàng)建切片,返回的是切片變量的指針s2 := new([]int)fmt.Printf("use new create slise type %T value %v \n",s2,s2)fmt.Printf("new s2 type %T value %v \n",*s2,*s2)// 想要賦值的話需要使用*解引用// 這里雖然不報(bào)語(yǔ)法錯(cuò)誤,但是如果嘗試直接使用(*s2)[0] = 123的話會(huì)有運(yùn)行時(shí)錯(cuò)誤,// panic: runtime error: index out of ranges2 = &s1 //需要將變量指針指向一個(gè)該類型變量的地址(*s2)[0] = 123(*s2)[4] = 3211fmt.Printf("new s2 type %T value %v \n",s2,s2)//s2的修改也會(huì)影響s1fmt.Printf("s1 type %T value %v \n",s1,s1)m1 := make(map[string]string)m1["name"] = "yangyanxing"m1["age"] = "30"fmt.Printf("m1 use make create type:%T value %v \n",m1,m1)m2 := new(map[string]string)fmt.Printf("m2 use new create type:%T value %v \n",m2,m2)//直接賦值會(huì)報(bào) panic: assignment to entry in nil mapm2 = &m1(*m2)["name"] = "fan"//對(duì)m2的修改也會(huì)影響到m1fmt.Printf("after m2 change m1 value is %v",m1)}

輸出結(jié)果為

use make create slise type []int value [0 0 0 0 0]make s1 type []int value [123 0 0 0 321]use new create slise type *[]int value &[]new s2 type []int value []new s2 type *[]int value &[123 0 0 0 3211]s1 type []int value [123 0 0 0 3211]m1 use make create type:map[string]string value map[name:yangyanxing age:30]m2 use new create type:*map[string]string value &map[]after m2 change m1 value is map[name:fan age:30]

map的初始化

map有以下兩種初始化方法

    使用make函數(shù)

    直接使用map初始化

    package mainimport "fmt"func main() {//使用make初始化mapmp2 := make(map[string]string)mp2["name"]  = "yangyanxing"mp2["age"] = "18"fmt.Println("m2 address ",&mp2)// out:m2 address  &map[name:yangyanxing age:18]mp3 := map[string]int{} //這里要有{},花括號(hào)里如果沒(méi)有內(nèi)容則說(shuō)明初始化了一個(gè)空字典mp3["yang"] = 18mp3["fan"] = 20fmt.Println(mp3)//out:map[yang:18 fan:20]mp4 := map[string]int{"yang":20,"fan":21, //即使是最后一個(gè)也要有逗號(hào)}fmt.Println(mp4)//out:map[yang:20 fan:21]mp5 := map[string]int{"yang":30} //寫在同一行則不用加逗號(hào)fmt.Println(mp5)//out: map[yang:30]mp6 := make(map[string]int,1) //還可以給map加一個(gè)容量mp6["yang"] = 30fmt.Println("mp6 lens is ",len(mp6),"address:",&mp6)//out:mp6 lens is  1 address: &map[yang:30]mp6["fan"] = 31fmt.Println("mp6 lens is ",len(mp6),"address:",&mp6)//out:mp6 lens is  2 address: &map[yang:30 fan:31]//也可以使用new,但是不可以直接對(duì)其進(jìn)行賦值,因?yàn)榇藭r(shí)它返回的是一個(gè)空指針//需要指向一個(gè)該類型的變量地址以后才可以進(jìn)行操作mp7 := new(map[string]int)fmt.Println(mp7)//out:&map[]//(*mp7)["yang"] = 100 //會(huì)報(bào)運(yùn)行時(shí)錯(cuò)誤mp7 = &mp6//mp7["fan"] = 1000 //也不可以直接使用mp7,需要使用* 先解引用(*mp7)["yang"] = 100 //這時(shí)就不會(huì)報(bào)運(yùn)行時(shí)錯(cuò)誤fmt.Println(mp7)//out:&map[yang:100 fan:31]}

    slice切片的初始化

    同樣可以通過(guò)make和切片本身進(jìn)行初始化

    package mainimport "fmt"func main() {//使用make初始化切片,需要傳一個(gè)len長(zhǎng)度,容量cap為可選//如果不傳的話則長(zhǎng)度和容量相同sls1 := make([]int,5,10)sls1[0] = 100//append 追加到尾部,這里有點(diǎn)意思sls1  = append(sls1,200)// ... 三個(gè)點(diǎn),go里的語(yǔ)法糖,展開(kāi)前面的切片sls1 = append(sls1,[]int{30,40}...)fmt.Println(sls1,len(sls1),cap(sls1))//out: [100 0 0 0 0 200 30 40] 8 10sls1 = append(sls1,3,4,6)//超過(guò)切片原有容量以后將會(huì)發(fā)生擴(kuò)容fmt.Println(sls1,len(sls1),cap(sls1))//out: [100 0 0 0 0 200 30 40 3 4 6] 11 20sls2 := make([]int,3)sls2[1] = 123fmt.Println(sls2,len(sls2),cap(sls2))//out: [0 123 0] 3 3//直接初始化sls3 := []int{}sls3 = append(sls3,10,20)fmt.Println(sls3,len(sls3),cap(sls3))//out: [10 20] 2 2sls4 := []int{1,2,3}sls5 :=[]int{1,2,5,//這里的逗號(hào)不能省}fmt.Println(sls4,sls5)//out: [1 2 3] [1 2 5]//使用new創(chuàng)建切片,和map一樣,返回的也是指針,不能直接對(duì)其進(jìn)行操作//需要先指向一個(gè)變量的地址sls6 := new([]int)fmt.Println(sls6)//out: &[]sls6 = &sls4fmt.Println(sls6) //out: &[1 2 3]}

    array數(shù)組的初始化

    數(shù)組不能使用make初始化,但是可以使用new初始化

    package mainimport "fmt"type person struct {name stringage int}func main() {fmt.Println("數(shù)組的初始化")//聲明并初始化一個(gè)空數(shù)組,里面的元素值為類型的零值arr1 := [2]int{}fmt.Println(arr1) //out: [0 0]//初始化時(shí)將元素值寫上arr2 := [2]int{1,3}fmt.Println(arr2) //out: [1 3]//只寫一個(gè),不寫的是零值arr3 := [2]int{1}fmt.Println(arr3) //out: [1 0]//arr4 := make([2]int) //數(shù)組不能使用makevar arr5 [2]intarr5[0] = 100fmt.Println(arr5)//[100 0]//不指定數(shù)組大小,使用... 三點(diǎn)號(hào)讓其自動(dòng)展開(kāi)計(jì)算arr6 := [...]int{2,4,6,8}fmt.Println(arr6,len(arr6))//out: [2 4 6 8] 4//使用new創(chuàng)建一個(gè)數(shù)組,得到的是一個(gè)指針arr7 := new([3]int)fmt.Println(arr7)//out: &[0 0 0]//可以直接對(duì)指針進(jìn)行操作arr7[0] = 3//和使用*解引用作用一樣(*arr7)[1] = 4fmt.Println(arr7) //out: &[3 4 0]}

    struct結(jié)構(gòu)體的初始化

    結(jié)構(gòu)體不能使用make,需要使用new和結(jié)構(gòu)體本身

    package mainimport "fmt"type person struct {name stringage int}func main() {fmt.Println("結(jié)構(gòu)體的初始化")//使用new,返回結(jié)構(gòu)體指針stru1 := new(person)fmt.Println(stru1)//out &{ 0} ,默認(rèn)是字段的零值//可以直接使用這個(gè)指針來(lái)操作變量//和使用*解引用效果一樣stru1.name = "yangyanxing"(*stru1).age = 18fmt.Println(stru1,*stru1) //&{yangyanxing 18} {yangyanxing 18}//只指定一個(gè)字段,沒(méi)有指定的默認(rèn)零值stru2 := person{name:"fan"}fmt.Println(stru2) //{fan 0}//全部指定,字段的順序可以不按照定義時(shí)的順序stru3 := person{age:18,name:"yang"}fmt.Println(stru3) //{yang 18}//按照結(jié)構(gòu)體順序初始化,這時(shí)元素的值必須都寫全了stru4 := person{"fan",17}fmt.Println(stru4) //{fan 17}}

到此,相信大家對(duì)“go語(yǔ)言中的new與make有什么區(qū)別”有了更深的了解,不妨來(lái)實(shí)際操作一番吧!這里是億速云網(wǎng)站,更多相關(guān)內(nèi)容可以進(jìn)入相關(guān)頻道進(jìn)行查詢,關(guān)注我們,繼續(xù)學(xué)習(xí)!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI