new()和make()是go语言中的内置函数,先来看下两个函数的说明
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.
func new(Type) *Type
new 会分配内存,第一个参数是变量类型。new 会创建一个未命名的Type类型的变量,初始化为Type类型的零值,并返回其地址(*Type)
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.
func make(t Type, size ...IntegerType) Type
make 方法也会分配内存,并初始化slice,map,chan类型的对象。和new一样第一个参数是变量类型,不过make方法返回值是一个Type类型的变量,不是指针。对于不同的参数类型,返回的结果不一样:
- slice: size参数指定了silce的长度,并且默认容量和长度一致,如过想指定silce的容量,需要指定第二个int参数(不能比size参数小,否则会报错),例如:make([]int, 0, 10) 将会分配一个底层长度为10的int数组,返回一个长度为0容量为10的silce
- map: 分配一个能够容纳指定数量元素的空map,如果size被忽略,将分配最小的内存
- channel: 初始化一个缓冲区大小为size的channel,如果忽略size,初始化一个无缓冲的channel
由此可见,make函数只是用来为silce,map,channel类型申请分配内存,而new可以为普通的数据类型申请内存。如果用new来给map申请空间是否可行呢
a := new(map[string]int)
fmt.Println(a)
// 输出
// &map[]
看起来也可以
a := new(map[string]int)
(*a)["age"]=12
fmt.Println(a)
// 结果
// panic: assignment to entry in nil map
使用的时候panic了
这时我们再看new()函数说明,new会分配内存,并初始化为零值,map的零值是nil,不能再nil上赋值,所以需要显式的赋值一次
a := new(map[string]int)
a = &map[string]int{}
(*a)["age"]=12
fmt.Println(a)
// 结果
//&map[age:12]
虽然可以用了,但感觉繁琐了