go语言隐藏了底层的细节,减少了可能的出错,提高了可移植性。但有时也需要放弃一些有益的保障来实现更高的性能。
unsafe就是打破go语言的保障,因为不可滥用,否则会带来各种不可预测的错误。并且在一些环境下,使用受限,广泛用于需要和操作系统交互的低级包中。(runtime, os, syscall和net)。
unsafe.Sizeof, Alignof和Offsetof
- unsafe.Sizeof返回传递参数在内存中占用的字节长度。
- unsafe.Alignof返回参数所要求的对对齐方式。
- unsafe.Offsetof返回成员f相对于结构体x其实地址的偏移值。
unsafe.Pointer
类似于c语言中的void*,可以存储任何变量的地址。可以在任意类型指针间进行转换。
例如,将*float64转为*uint64:
package main
func Float64its(f float64) uint64 {
return *(*uint64)(unsafe.Pointer(&f))
} 特别要注意,指针不要引入uintptr来使用,这是因为垃圾回收器会将内存中的变量进行移动来减少内存碎片,unsafe.Pointer是一个指针,变量移动,它的值也会改变。但是uintptr的值不会随着变量移动改变。可以会出现错误。
因为unsafe.Pointer转为uintptr都将它看作一个变量的旧地址。 当调用一个返回uintptr类型的库函数时,例如reflect包中的函数,这些结果应该立刻转换为unsafe.Pointer来确保继续指向同一个变量。