https://go101.org/article/value-part.html
部分内容摘要
go中两大类型分类
go可以被视为C家庭语言,go和c语言在struct和指针类型的内存结构上有很多的相似之处。
另一方面,go也被视为c语言框架的。主要反映在,go支持的类型中有几种是内存结构不透明的,而c语言的内存结构是透明的。每个c值在内存中被封装到一个内存块中。而go有几种类型会存在多个内存块中。
go类型分为两大类:
只存放在一个内存块中的类型 | 存放在多个内存块中的类型 |
---|---|
solo Direct value part(直接指向值部分) | direct part->underlying part(还引用到底层下部分) |
boolean types | slice types |
numeric types | map types |
pointer types | channel types |
unsafe pointer types | function types |
struct types | interface types |
array types | string types |
注意:
-
接口和string的值是否包含底层部分(underlying parts)是由编译器决定的。标准go编译器是包含的。
-
函数值是否可能包含基础部分几乎很难甚至无法证明。go 101里视函数可能包含underlying parts的。
第二类中的类型种类通过封装许多实现细节为Go编程带来了很多便利。
go中的两种指针类型
type-safe pointer types和 type-unsafe pointer types。 包unsafe里有unsafe.Pointer类型,与c语言中void*相似。下面文中提到指针包含这两种指针。
指针指向另外一个值的地址,除非它是nil指针。我们说指针引用了这个值,或这个值被这个指针引用。值可以被隐式引用。
-
如果结构值a中有个指针字段b它引用了一个值c,我们可以说a也引用了c。
-
x引用了y,y又引用了z,我们说x间接引用了z。不管x->y,y->z是直接还是间接引用。
引用关系是可以传递的。
第二类类型的可能内部定义
为了更好了解,可以假想第二分类类型是由第一分类类型实现。
内部关于map, channel, function类型的定义类似如下:
// map types type _map *hashtableImpl // channel types type _channel *channelImpl // function types type _function *functionImpl
slice的实现可能如下 :
type _slice struct { // referencing underlying elements elements unsafe.Pointer // number of elements and capacity len, cap int }
string如下 :
type _string struct { elements *byte // referencing underlying bytes len int // number of bytes }
普通的interface
type _interface struct { dynamicType *_type // the dynamic type dynamicValue unsafe.Pointer // the dynamic value }
标准go编译器的non-blank interface
type _interface struct { dynamicTypeInfo *struct { dynamicType *_type // the dynamic type methods []*_function // method table } dynamicValue unsafe.Pointer // the dynamic value }
Underlying Value Parts在赋值中不会被拷贝
现在我们了解到,第二类中类型的内部定义是指针持有者(指针或指针包装器)类型。知道这一点对理解Go中的价值复制行为非常有帮助。
在Go中,在目标值和源值具有相同的类型下,每个值的赋值(包括参数传递等)都是浅拷贝( shallow value copy)(如果它们的类型不同,我们可以认为在执行该赋值之前,源值将隐式转换为目标类型)。也就是说,源值中只有直接部分被拷贝到目标值中。如果源值中包含underlying value parts,然后目标值和源值的直接部分都引用了同样的underlying value part(s),它们是共享同样的underlying value part(s)。