Go 语言中的 new 关键字和 make 关键字的区别
Contents
Go 语言分配内存的函数包括 new 和 make。new 用来获取类型对应的指针类型,即要获取指针类型的内存分配。make 只用来分配引用类型,即为channel,map,slice分配内存。
对于值类型的变量,我们通过var 声明,系统会默认为他分配内存空间,并赋该类型的零值。如下,我们声明一个int类型变量i,输出为0。
package main
import "fmt"
func main() {
var i int
fmt.Println(i)
}
而如果我们声明一个指针类型的变量,系统不会为他分配内存,改变量默认就是nil。此时如果你想直接使用,那么系统会抛异常。
var j *int
fmt.Println(j)
*j = 10 //panic: runtime error: invalid memory address or nil pointer dereference
也就是说,空指针还没有内存分配,是不能使用的。那么要想使用,此时就需要new出场啦。
var j *int
j = new(int)
fmt.Println(j)
fmt.Println(*j)
*j = 10
fmt.Println(*j)
0xc00000a0e0
0
10
声明指针类型变量后,通过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.
func new(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 是分配内存并初始化,初始化并不是置为零值。
- 与new一样,它的第一个参数也是一个类型,但是不一样的是,make返回的是传入的类型,而不是指针!
var c chan int
fmt.Printf("%#v \n",c) //(chan int)(nil)
c = make(chan int)
fmt.Printf("%#v", c) //(chan int)(0xc000062060)
声明管道类型变量c,此时c还是nil,不可用;通过make来分配内存并初始化,c就获得了内存可以使用了。