笔记 - unsafe
Package unsafe contains operations that step around the type safety of Go programs.
Packages that import unsafe may be non-portable and are not protected by the Go 1 compatibility guidelines.
unsafe 库让 golang 可以像C语言一样操作计算机内存,但这并不是golang推荐使用的,能不用尽量不用,就像它的名字所表达的一样,它绕过了golang的内存安全原则,是不安全的,容易使你的程序出现莫名其妙的问题,不利于程序的扩展与维护。
unsafe.Sizeof
Sizeof takes an expression x of any type and returns the size in bytes of a hypothetical variable v as if v was declared via var v = x. The size does not include any memory possibly referenced by x.
For instance, if x is a slice, Sizeof returns the size of the slice descriptor, not the size of the memory referenced by the slice. The return value of Sizeof is a Go constant.
func Sizeof(x ArbitraryType) uintptr
unsafe.Sizeof接受任意类型的值(表达式),返回其占用的字节数, 这个大小标识类型存储大小,和类型对应的变量存储的内容大小无关. 如果x为一个切片,sizeof返回的大小是切片的描述符,而不是切片所指向的内存的,对于数组来说,sizeof(arr)的值是在随着arr的元素的个数的增加而增加
Sizeof函数返回的值,对于基础数据类型来说是系统可以预分配给该类型变量占用的字节数,对于字符串类型,引用类型和结构体等聚合类型来说只包括数据结构中固定的部分,例如字符串对应结构体中的指针和字符串长度部分,但是并不包含指针指向的字符串的内容。Go语言中非聚合类型通常有一个固定的大小,尽管在不同工具链下生成的实际大小可能会有所不同。考虑到可移植性,引用类型或包含引用类型的大小在32位平台上是4个字节,在64位平台上是8个字节。
bool 类型虽然只有一位,但也需要占用1个字节,因为计算机是以字节为单位64为的机器,一个 int 占8个字节string 类型占16个字节,内部包含一个指向数据的指针(8个字节)和一个 int 的长度(8个字节)slice 类型占24个字节,内部包含一个指向数据的指针(8个字节)和一个 int 的长度(8个字节)和一个 int 的容量(8个字节)map 类型占8个字节,是一个指向 map 结构的指针可以用 struct{} 表示空类型,这个类型不占用任何空间,用这个作为 map 的 value,可以将 map 当做 set 来用
不论字符串的len有多大,sizeof始终返回16,这是为啥,字符串不是也是不可变的吗?
type stringStruct struct { str unsafe.Pointer len int
}
字符串使用 16 字节长的数据结构表示,包含一个指向字符串存储数据的指针和一个长度数据。采用字符串切片生成新的字符串的时候不会涉及到内存的分配和复制操作,因为多个字符串重用了底层的存储数据,因为字符串是不可变的(改变字符串会生成新的字符串),不会有内存共享问题。Go 使用 utf-8 编码字符串,(utf-8编码作者是 Go 作者之一),Go 的字符串每一个字符是 rune,rune 是 uint32 的别名,unicode 字符的长度可能是1,2,3,4个字节。如果统计字数算的是 rune。
常用数据类型对应的存储字节大小(Sizeof输出):