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

參考教程:
http://www.flysnow.org/2017/03/26/go-in-action-go-type.html
http://www.flysnow.org/2017/10/23/go-new-vs-make.html

1 變量的類型

想弄明白 make 和 new 的區(qū)別短蜕,首先要分清楚引用類型和值類型。

1.1 值類型

golang 中內(nèi)置原始數(shù)據(jù)類型是值類型坡倔。比如int若专、float、string窖杀、bool漓摩。值類型是不可變的,所以對他們進(jìn)行操作入客,一般會返回一個(gè)新創(chuàng)建的值管毙。把這些值傳遞給函數(shù)時(shí),其實(shí)創(chuàng)建的是一個(gè)值的副本桌硫。這一點(diǎn)在python中也是相同的夭咬。作為參數(shù)傳遞給函數(shù)的都是一個(gè)副本。

func main(){
  s := "a"
  modify(s)
  fmt.Println(s)
}

func modify(s string)string{
  s = "888888888"
}

因?yàn)樾薷闹殿愋兔傻亩际撬囊粋€(gè)副本卓舵,所以值類型在多線程中是安全的。

1.2 引用類型

切片膀钠、map掏湾、接口、函數(shù)類型以及chan都是引用類型肿嘲。引用類型的修改可以影響到任何引用到它的變量融击。

引用類型之所以可以引用,是因?yàn)槲覀冊趧?chuàng)建引用類型的變量雳窟,其實(shí)是一個(gè)標(biāo)頭值砚嘴,標(biāo)頭值里包含一個(gè)指針,指向底層的數(shù)據(jù)結(jié)構(gòu),在函數(shù)中傳遞引用類型時(shí)际长,傳遞的是這個(gè)標(biāo)頭值的副本耸采,它所指向的底層結(jié)構(gòu)并沒有被復(fù)制傳遞,這也是引用類型傳遞高效的原因工育。

func main(){
  ages := map[string]int{"s":12}
  modify(ages)
  fmt.Println(ages)
}
func modify(m map[string]int){
  m["s"] = 777
}

函數(shù) modify 的修改虾宇,會影響 ages 的值。

1.3 結(jié)構(gòu)類型

用 var 關(guān)鍵字聲明一個(gè)結(jié)構(gòu)體類型的變量如绸。

type person struct{
  age int
  name string
}
// 聲明
var p person

這種 var 聲明的方式计寇,會對結(jié)構(gòu)體 person 里的數(shù)據(jù)類型默認(rèn)初始化第喳,也就是使用它們類型的零值。
函數(shù)傳參是值傳遞,所以對于結(jié)構(gòu)體來說也不例外夷磕,結(jié)構(gòu)體傳遞的是其本身以及里面的值的拷貝撮慨。

type Person struct {
    age int
    name string
}

func modify(p Person){
    p.age  = 100000000000
}

func main(){
    jim := Person{10,"jim"}
    fmt.Println(jim)
    modify(jim)
    fmt.Println(jim)
}

以上的輸出都是一樣的纹腌,所以我們驗(yàn)證傳遞的是值的副本肖抱。如果上面的例子我們要修改 age 的值可以通過傳遞結(jié)構(gòu)體的指針。

type Person struct {
    age int
    name string
}

// 我覺得這樣比較好理解瓦侮,*Person 是針對結(jié)構(gòu)體實(shí)例的操作艰赞。(可以想想面向?qū)ο蟮恼Z言,Python / Java)
func modify(p *Person){
    p.age  = 100000000000
}

func main(){
// jim 的類型是 Person
    jim := Person{10,"jim"}
// var jim Person = Person{10, "jim"}
    fmt.Println(jim)
// &jim 指向的是實(shí)例
    modify(&jim)
// var h *Person = &jim
    fmt.Println(jim)
// * 號在定義時(shí)使用肚吏,&在運(yùn)算時(shí)使用方妖。*這種類型在運(yùn)算時(shí)映射的值是&
}

1.4 自定義類型

type Duration int64

Go是強(qiáng)類型語言,所以 int64 與 Duration不能直接賦值罚攀。

2 變量的聲明

var i int
var s string

變量的聲明可以通過 var 關(guān)鍵字党觅,然后就可以在程序中使用了,var 聲明的變量的值是他們默認(rèn)的零值斋泄。

類型 默認(rèn)零值
int 0
string ""
引用類型 nil

對引用類型賦值杯瞻。
*int,是聲明一個(gè)值類型int的引用類型是己。
*i,是對值類型的引用類型進(jìn)行運(yùn)算又兵。

func main(){
  var i *int
  *i = 10
  fmt.Println(*i)
}

運(yùn)行時(shí)的 paninc : runtime error: invalid memory address or nil pointer dereference
從這個(gè)提示中可以看出任柜,對于引用類型的變量卒废,我們不光是聲明它,還要為它分配內(nèi)存空間宙地,否則我們的值放在哪去呢摔认?這就是上面錯(cuò)誤提示的原因。
對于值類型的聲明則不需要宅粥,是因?yàn)橐呀?jīng)默認(rèn)幫我們分配好了参袱,值類型都有一個(gè)默認(rèn)零值。
要分配內(nèi)存,就引出來今天的new 和 make抹蚀。

new

func main(){
  var i *int
  i = new(int)
  *i = 10
  fmt.Println(*i)
}

看下 new 這個(gè)內(nèi)置的函數(shù)

// The new built-in function allocates memory.The first argument is a type,not a value, and the value returned is a pointer to a newly allocated zero value of that type.
func new(Type) *Type

new 是一個(gè)分配內(nèi)存的內(nèi)置函數(shù)剿牺。new的參數(shù)是一個(gè)類型,new的返回值是一個(gè)指針环壤。該指針指向參數(shù)的默認(rèn)零值晒来。

func main(){
// 這個(gè)u 是什么類型,*user, 為啥郑现?因?yàn)閚ew函數(shù)返回的是一個(gè)指向參數(shù)類型默認(rèn)零值的指針啊湃崩。
// 這種方式和上文中 u := user{}, &u 的方式實(shí)際上是一樣的。
    u := new(user)
    u.lock.Lock()
    u.name = "sssssssss"
    u.lock.Unlock()
    fmt.Println(u)
}

type user struct {
    lock sync.Mutex
    name string
    age int
}

這就是 new,它返回的永遠(yuǎn)是類型的指針接箫,指向分配類型的內(nèi)存地址攒读。

make

make 也用于內(nèi)存分配,但是和 new 不同辛友,它只用于 chan / map 和 且切片的內(nèi)存創(chuàng)建薄扁,而且它返回的類型就是這三個(gè)類型本身,而不是它們的指針類型瞎领。因?yàn)閏han / map / 切片已經(jīng)是引用類型了泌辫,所以沒必要返回他們的指針了。
看一下 make 的文檔

The make built-in function allocates and initializes an object of type slice, map, or chan (only).Like new,the argument is a type, not a value.Unlike new, make's return type is the same as the type of its argument,not a pointer to it. The specification of the result depends on the type:

Slice: the size specifies the length. The capacity of the slice is equal to its length.A second integer argument may be provided to specify a different capacity; it must be no smaller than the length, so make([]int,0,10) allocates a slice of length 0 and capacity 10.

Map: An empty map is allocated with enough space to hold the specified number of elements.The size may be omitted,in which case a small starting size is allocated.

Channel: The channel's buffer is initialized with the specified buffer capacity. If zero, or the size is omitted, the channel is unbuffered.

func make(t Type, size ...IntegerType) Type

make 只為 slice/ map/ chan 初始化九默,分配內(nèi)存震放。
和new 類似,第一個(gè)參數(shù)必須是一個(gè)類型驼修。和 new 不同的是殿遂,new 返回的是參數(shù)類型的指針,指針指向的該參數(shù)的默認(rèn)零值乙各。而make返回的是傳入類型相同墨礁,并不是指針。因?yàn)?slice / map / chan 本身就是引用類型了耳峦。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末恩静,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子蹲坷,更是在濱河造成了極大的恐慌驶乾,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件循签,死亡現(xiàn)場離奇詭異级乐,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)县匠,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進(jìn)店門风科,熙熙樓的掌柜王于貴愁眉苦臉地迎上來撒轮,“玉大人,你說我怎么就攤上這事贼穆√馍剑” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵故痊,是天一觀的道長臀蛛。 經(jīng)常有香客問我,道長崖蜜,這世上最難降的妖魔是什么浊仆? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮豫领,結(jié)果婚禮上抡柿,老公的妹妹穿的比我還像新娘。我一直安慰自己等恐,他們只是感情好洲劣,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著课蔬,像睡著了一般囱稽。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上二跋,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天战惊,我揣著相機(jī)與錄音,去河邊找鬼扎即。 笑死吞获,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的谚鄙。 我是一名探鬼主播各拷,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼闷营!你這毒婦竟也來了烤黍?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤傻盟,失蹤者是張志新(化名)和其女友劉穎速蕊,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體莫杈,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡互例,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年奢入,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了筝闹。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片媳叨。...
    茶點(diǎn)故事閱讀 38,018評論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖关顷,靈堂內(nèi)的尸體忽然破棺而出糊秆,到底是詐尸還是另有隱情,我是刑警寧澤议双,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布痘番,位于F島的核電站,受9級特大地震影響平痰,放射性物質(zhì)發(fā)生泄漏汞舱。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一宗雇、第九天 我趴在偏房一處隱蔽的房頂上張望昂芜。 院中可真熱鬧,春花似錦赔蒲、人聲如沸泌神。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽欢际。三九已至,卻和暖如春矾兜,著一層夾襖步出監(jiān)牢的瞬間损趋,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工椅寺, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留舶沿,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓配并,卻偏偏與公主長得像括荡,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子溉旋,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內(nèi)容