Golang的内存分配make,new详解
Golang内存分配主要有三种方式:new,make,以及大括号({})。常常在使用上容易混乱,弄不清楚。
New
采用New返回的是一个指针,即指向一个被初始化为0值得地址。
p := new(int) // p is a address that point to value of int, value is zeroed
p 是一个指针,指向一个类型为int的并被初始化为0的值。
type SyncedBuffer struct {
lock sync.Mutex
buffer bytes.Buffer
}
p := new(SyncedBuffer) // type *SyncedBuffer
var v SyncedBuffer // type SyncedBuffer
p 也是一个指针,指向一个类型为SyncedBuffer的值,这个值里面lock,buffer全部被初始化为0.
所以可以看出,New可以用于数据类型,以及数据结构的内存分配,返回一个地址,并将相关值全部初始化为0.
Make
make仅仅用于slice,map,channel的内存分配,与New不同的是,采用make分配内存,并不是返回一个地址,而是直接返回类型值,且值也不是被初始化为0,而是可以被指定初始化。
var v []int = make([]int, 10, 100)
v是一个slice,根据slice的结构我们可以知道,len被初始化为10, cap被初始化100,而data被指向
一个10个元素的数组。假设如果用New会怎么样呢。
var p *[]int = new([]int)
这个p一个指针,而里面的值会被初始化为0,那么就相当于*p == nil,一用就会奔溃。
Call Type T Result
make(T, n) slice slice of type T with length n and capacity n
make(T, n, m) slice slice of type T with length n and capacity m
make(T) map map of type T
make(T, n) map map of type T with initial space for approximately n elements
make(T) channel unbuffered channel of type T
make(T, n) channel buffered channel of type T, buffer size n
注意n和m的取值:
- 取值范围必须要是int,一定是正数
- n ≤ m
大括号(Composite literals)
与make和new不同,{} 适用性比较广, 并可直接赋值初始化,可以用于slice,map,struct等等
f := new(File)
v := &File{}
t := &File{fd: fd, name: name}
如果不对类型做赋值,那么和new的效果是一样的,f与v是等价的,也是被初始化为0,并返回一个指针。当然如果不想被初始化为0,也可以针对每个值做赋值,如t。
// Arrays
elements := []int{1, 2, 3, 4}
// Struct definition
type Thing struct {
name string
generation int
model string
}
// Positional fields
thing1 := Thing{"Raspberry Pi", 2, "B"}
// Explicit field names as key
thing2 := Thing{name: "Raspberry Pi", generation: 2, model: "B"}
用于arrays,struct, map,对里面的每个值做初始化,并返回