Go 值类型与引用类型
值类型
- int/uint
- float
- bool
- string
- interface
- 结构体
- 数组
- 指针
- 函数
值类型的特点
值类型变量直接存储值,在初始化值类型变量的同时会赋予该变量一个零值。
对值类型变量进行拷贝,然后对拷贝后的变量进行修改操作,不会影响原变量的值。
引用类型
- slice
- chan
- map
引用类型的特点
引用类型零值为nil(还未被make之前)
引用类型底层通常由一个结构体实现,这个结构体内部有个指针,指向了引用类型数据存储的内存空间。
引用类型通过make函数进行初始化(slice切片是个例外,可以不用make,直接append添加新元素),make直接返回引用类型本身(可以理解为直接返回一个创建好的结构体对象,这个对象内部封装了一个指向实际存储空间的指针)。
在对引用类型对象进行拷贝时,只是拷贝了对象的值,但是这个对象结构体内指向实际存储空间的指针地址并不会改变。原对象和拷贝对象虽然是两个处于不同内存空间的对象,但它们的底层仍指向同一个内存空间,所以此时对拷贝对象的修改操作也会影响到原对象。
有一种情况会导致对拷贝对象修改后原对象不变,那就是在拷贝了一个slice切片后,对拷贝切片进行append操作时,如果拷贝切片的容量不足,引起扩容。切片的扩容机制是:另外申请一块新的内存空间,将原内存空间的数据都搬迁到新内存空间里,然后slice底层结构体内的指针指向新的存储空间。所以当拷贝切片触发扩容后,它的实际存储空间地址发生变更,后续再对拷贝切片进行append操作也不会再影响到原切片。
- 切片的底层结构
type SliceHeader struct {
Data uintptr //指向底层数组空间的指针
Len int
Cap int
}