1. 程式人生 > >golang 使用make、new和append的注意細節

golang 使用make、new和append的注意細節

使用append向slice追加元素遇到的坑,在此總結一下。

一,細節1

urls := make(map[string]string, 3) 
urls["baidu"] = "www.baidu.com"
urls["google"] = "www.google.com"
urls["csdn"] = "www.csdn.net"
names := make([]string, len(urls))
for key, _ := range urls {
    names = append(names, key)
    }
fmt.Println(names,len(names))

輸出結果
[ csdn baidu google] 6
前面多了幾個空格,長度為6,與預期的結果不一致
修改程式碼

names := make([]string, 0)
for key, _ := range urls {
    names = append(names, key)
}
fmt.Println(names,len(names))

或者

var names []string
for key, _ := range urls {
    names = append(names, key)
}
fmt.Println(names,len(names))

輸出結果
[baidu google csdn] 3
總結:append無論如何都是從slice的尾部開始追加資料,原來的slice只有3個長度,現在每一次append都要重新分配一次記憶體

二、細節2

s1 := []int{1, 2, 3}
s2 := []int{4, 5}
s1 = append(s1, s2)
fmt.Println(s1)

程式報錯:cannot use s2 (type []int) as type int in append
修改為:

s1 := []int{1, 2, 3}
s2 := []int{4, 5}
s1 = append(s1, s2...)
fmt.Println(s1)

輸出結果:
[1 2 3 4 5]
總結:append切片時候別漏了’…’

三、細節3
new與make區別:
new只分配記憶體它並不初始化記憶體,只是將其置零。new(T)會為T型別的新專案,分配被置零的儲存,並且返回它的地址,一個型別為T的值,也即其返回一個指向新分配的型別為T的指標,這個指標指向的內容的值為零(zero value),注意並不是指標為零。比如,對於bool型別,零值為false;int的零值為0;string的零值是空字串。
make用於slice,map,和channel的初始化,返回一個初始化的(而不是置零),型別為T的值(而不是T)。之所以有所不同,是因為這三個型別是使用前必須初始化的資料結構。例如,slice是一個三元描述符,包含一個指向資料(在陣列中)的指標,長度,以及容量,在這些項被初始化之前,slice都是nil的。對於slice,map和channel,make初始化這些內部資料結構,並準備好可用的值。

p := new([]int) //p == nil; with len and cap 0,被置零的slice結構體的指標,即指向值為nil的slice的指標
fmt.Println(p)
v := make([]int, 10, 50) // v is initialed with len 10, cap 50
fmt.Println(v)

輸出結果:
&[]
[0 0 0 0 0 0 0 0 0 0]

new1 := new([2]int)
fmt.Println(new1)
new1[0] = 1
new1[1] = 2
fmt.Println(new1)

輸出結果:
&[0 0]
&[1 2]