背景:
关于Go语言的变量主要分为值类型和引用类型两种:
1. Go语言中的值类型和引用类型
- 值类型:int,float,bool,string,struct和数组 (数组要特别注意,别搞混了)
变量直接存储值,分配栈区的内存空间,这些变量所占据的空间在函数被调用完后会自动释放。
- 引用类型:slice,map,chan和值类型对应的指针
变量存储的是一个地址(或者理解为指针),指针指向内存中真正存储数据的首地址。内存通常在堆上分配,通过GC回收。
注意:
值类型直接存储的是值本身,存放在栈区,会随着函数被调用后自动的释放;
引用类型则存储的是地址也就是我们讲的c语言指针,存放在堆内存中,会通过GC机制进行回收。
2. new() vs make() (简单点讲就是上面所说的引用类型)
new() (new()方法就是为 int/bool/struct等 值类型分配内存空间,返回相应类型的指针)
该方法的参数要求传入一个类型,而不是一个值,它会申请一个该类型大小的内存空间,并会初始化为对应的零值,返回指向该内存空间的一个指针。如下:
// 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是一样的,但是new不仅仅会申请内存同时还会进行初始化,不会出现空指针异常的问题。
q:=new(int)
fmt.Println(*q) //结果等于0
var p *int
fmt.Println(*p) //直接报错,因为开辟的内存为空,就是空指针异常
make() (一种特殊的引用类型和new返回的指针类型不同)
make也是用于内存分配,但是和new不同,它只用于slice、map和channel的内存创建,它返回的类型就是类型本身,而不是它们的指针类型。
// 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相似之处在于都会进行相关的初始化数据:
s :=make(map[string]interface{})
fmt.Println(s)