Go new與make的介紹與差異 [Golang]

Posted by Kubeguts on 2020-11-08

Golang中,makenew都是建構變數來使用

new的介紹

new(T)會建構一個T型別的 “沒有名字” 的變數,以T的zeroed value來初始化T,且new(T) 回傳 “指向T的指標”

  • 若T是 string,那zeroed值為 ""
  • 若T是 int,那zeroed值為 0
  • 若T是 channel, func, map, slice,那zeroed值為 nil

範例

1
2
3
4
5
6
7
p := new(int) // 宣告一個指向int不具名變數的`指標p`,`指標p`指向一個初始化的zeroed value為0

fmt.Print(*p) // 印出 0

*p = 2 // 將不具名變數的值設置為2

fmt.Print(*p) // 印出 2

其中new算是golang語法的簡寫,其中

1
2
3
func newInt() *int {
return new(int)
}

就等於下列寫法

1
2
3
4
func newInt() *int {
var dummy int
return &dummy // 回傳dummy的指標
}

注意: 謹慎操作new出來的map

因為用new初始化的map會是 nil map,故以下操作會出現panic

1
2
3
4
5
6
7
8
func main() {
book := new(map[string]string)
// 宣告一個指標叫做book, 指向一個map為index是string
// 映射到string型態的book名稱

b := *book // 取得book指標所指向的map
b["ISBN-001"] = "go programming language" // panic: assignment to entry in nil map
}

上述範例會出錯的原因是因為, b是一個nil map,沒有指向任何的記憶體位置,所以對一個nil值操作當然會冒出error

解法就得透過 make 方法為nil map分配確定的內存地址了

new 不是 Keyword

要注意一點是 new 並非是golang的關鍵字,故可以在func內重新宣告

1
2
3
func delta(old, new int) int {
return new - old
}

make的介紹

  • make(T, args)用來為 slices, maps, 以及 channel分配其記憶體位址的空間與初始化值,並回傳一個型態T的參考!
  • make不會回傳指標!

範例

1
2
3
4
5
6
func main() {
books := make([]string, 100) // 初始化長度為100的book字串陣列,每個array內的值都是 ""

receiver := make(chan string) // 初始化channel,但不會回傳指標
booksMapper := make(map[string]string)
}

由於make回傳的是參考,所以若將make宣告的s2 傳給func modifySlices2做修改時,也會影響s2的內容

1
2
3
4
5
6
7
8
func modifySlice(s []int) {
s[0] = 1
}

s2 := make([]int, 3)
fmt.Printf("%#v", s2) // s2為 []int{0, 0, 0}
modifySlice(s2)
fmt.Printf("%#v", s2) // s2被modifySlice()方法給變成 []int{1, 0, 0}

new與make的差異

  • new會回傳指標,但是初始化的值為zeroed value,特別是在對map做初始化時,其zeroed valued為 nil,意思就是不會分配其記憶體位置
  • make只能用來對特別型態(如map, slice, func, channle)分配其記憶體內存地址,以及為這些特殊型態設定該初始值 (string就是"", int為0)

所以若要傳指標時,就需要考慮用new,而非是make

參考