介绍:
Golang 语言中的unsafe 包中包含的操作绕过了Golang 程序的类型安全检查,直接操作内存,从而达到提升性能的目的,导入unsafe 包可能是不可移植的,并且不受 Go1 兼容性准则的保护,所以我们应该谨慎使用。
下面主要介绍unsafe 包的 unsafe.Pointer ,它表示任意类型的指针,他类似于C语言中的无类型指针,void* , 可以作为指针类型 * T 和 uintptr 类型值之间相互转换的中转站。
我们知道 Golang 语言中指针类型是 * T ,表示一个指向T类型变量的指针,因为Golang 语言是强类型的静态语言, 为了安全考虑,规定两个不同的指针类型之间不可以相互转换,比如 *int 不能与 * float32 相互转换,但是,实际上是可以使用 unsafe.Pointer 进行转换。
在比如Golang 语言中的内置数据类型,uintptr 也可以表示任何指针,它实际的数值类型,可以用于存储内存地址。它和unsafe.Pointer 最大的区别是 unsafe.Pointer 不支持指针运算,比如 + 运算符 ,但是 uintptr 可以支持。
unsafe.Ponter 类型
有了前面内容的铺垫,我们开始介绍unsafe.Ponter ,它表示指向任意类型的指针,以下是unsafe 的代码。
type ArbitraryType int
type Pointer *ArbitraryType
unsafe.Ponter 类型有四个准换规则:
- 任何类型的指针值*T 都可以转换位unsafe.Pointer
- unsafe.Pointer 可以转换为任何类型的指针值。
- uintptr 可以转换为unsafe.Pointer
- unsafe.Pointer 可以转换为 uintptr。
unsafe.Pointer 允许程序绕过类型安全检查读写任意内存,所以使用适应格外小心。
unsafe.Pointer 包含6个使用模式。
使用
unsafe.Pointer
作为中转,将一个指针类型*T
转换为另外一个指针类型*T
。将
unsafe.Pointer
转换为 uintptr(但不返回给unsafe.Pointer
),然后使用 uintptr 值。将
unsafe.Pointer
转换为 uintptr,然后使用 uintptr 值进行算术运算,最后将运算结果 uintptr 值再转换为unsafe.Pointer
调用
syscall.Syscall
时,将unsafe.Pointer
转换为 uintptr 值,作为参数传递。将
reflect.Value.Pointer
或reflect.Value.UnsafeAddr
的返回结果 uintptr 值,从 uintptr 转换为unsafe.Pointer
。将
reflect.SliceHeader
或reflect.StringHeader
值的 Data 字段与unsafe.Pointer
进行转换。