Golang面試make和new的用法
在golang中,make和new都分配內存,但是它們之間仍然存在一些差異。只有了解它們之間的差異,才能在適當的場合使用它們。
簡而言之,new只是分配內存,而不初始化內存;make分配并初始化內存。所謂的初始化就是給一個類型賦一個初始值,例如,字符為空,整數為0,邏輯值為false。
從Golang的官方文檔的builtin(內置的軟件包)中可以找到,make和new的用法。

官方文檔的內置的軟件包
new的使用介紹:
我們先來看看new的定義
- // 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.
- //內建函數new分配內存。其第一個實參為類型,而非值。其返回值為指向該類型的新分配的零值的指針。
- func new(Type) *Type
可以看出,它的參數是一個類型,返回值是指向該類型的內存地址的指針,并且分配的內存將被設置為零,即該類型的零值,即字符為空,整數為0,邏輯值為false
看一些例子
- type P struct {
- Name string
- Age int
- } var a *[2]int
- var s *string
- var b *bool
- var i *int
- var ps *P
- a = new([2]int)
- s = new(string)
- b = new(bool)
- i = new(int)
- ps = new(P) //structure
- fmt.Println(a, " ", *a)
- fmt.Println(s, " ", *s)
- fmt.Println(b, " ", *b)
- fmt.Println(i, " ", *i)
- fmt.Println(ps, " ", *ps)
輸出如下:
- &[0 0] [0 0]
- 0xc0000821e0
- 0xc0000a409a false
- 0xc0000a40b0 0
- &{ 0} { 0}
上面基礎類型,我們看一下slice, map and channel類型是如何操作的:
- //map 操作
- var mp *map[string]string
- mp = new(map[string]string)
- //注釋掉下面的行,new map 返回為nil,直接使用會panic
- //*mp = make(map[string]string) // if this line is omitted, it will pan "Pan: assignment to entry in nil map"“
- (*mp)["name"] = "lc"
- fmt.Println((*mp)["name"])
- // slice 操作 var ms *[]string
- ms = new([]string)
- // 注釋掉下面的行訪問的時候會下標超出范圍 //*ms = make([]string,5) // if this line is deleted, it will "panic: runtime error: index out of range"
- (*ms)[0] = "lc"
- fmt.Println((*ms)[0])
從上面可以看出,silce,map,channel和其他類型是引用類型。當引用類型初始化為nil時,不能直接分配nil,也不能使用new來分配內存,還需要使用make來進行分配。
make的使用介紹:
我們看一下make的定義
- / /The make built-in function allocates and initializes an object of type
- // slice, map, or chan (only). Like new, the first 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. For example, make([]int, 0, 10) allocates an underlying array
- // of size 10 and returns a slice of length 0 and capacity 10 that is
- // backed by this underlying array.
- // 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.
- //切片:size指定了其長度。該切片的容量等于其長度。切片支持第二個整數實參可用來指定不同的容量; 它必須不小于其長度,因此 make([]int, 0, 10) 會分配一個長度為0,容量為10的切片。
- //映射:初始分配的創建取決于size,但產生的映射長度為0。size可以省略,這種情況下就會分配一個小的起始大小。
- //通道:通道的緩存根據指定的緩存容量初始化。若 size為零或被省略,該信道即為無緩存的。
- func make(t Type, size ...IntegerType) Type
可以看出,它返回的是類型本身而不是指針類型,因為make只能為slice,map,channel等初始化內存,并且它們返回引用類型,因此不必返回指針
讓我們看一些make的例子:
- mm :=make(map[string]string)
- mm["name"] = "lc"
- fmt.Println(mm["name"])
- mss :=make([]int,2)
- mss[0] = 100
- fmt.Println(mss[0])
- ch :=make(chan int,1)
- ch <-100
- fmt.Println(<-ch)
總結:
make僅用于分配和初始化slice,map和chan類型的數據。new可以分配任何類型的數據。new分配返回一個指針,即Type * Type。make返回一個引用,該引用為Type由make分配的空間之后,清除并初始化由new分配的空間。