unsafe.Pointer 类似于C语言的void*
官方文档对该类型的四个描述:
- 任何类型的指针都可以转换为Pointer
- Pointer类型可以转换为任意类型的指针
- uintptr可以被转化为Pointer
- Pointer可以被转化为uintptr
利用unsafe.Pointer来突破私有成员
type V struct{
i int32
j int64
}
func Test(){
var v *V=new(V)
//由于i,j是私有成员 不能直接访问 下面利用unsafe.Pointer修改i,j的值
var i *int32=(*int32)(unsafe.Pointer(v))//通过unsafe.Pointer将v转换为*int32
//此时i 指向的地址是结构体的首地址 也就是V.i的地址
*i=int32(666)//解引用修改i的值
fmt.Printf("%d\n",*i)//666
//获取j的地址方法1:结构体v的首地址 加上j在结构体中偏移(包含空洞)
var j *int64=(*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(v))+unsafe.Offsetof(v.i)))
//获取j的地址方法2:结构体v的首地址 加上i所占位置 go计算类型大小跟C有点不一样 C直接sizeof类型 go是sizeof变量
//var j *int64=(*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(v))+uintptr(unsafe.Sizeof(int32(0)))))
*j=int64(777)
fmt.Println(*j) //777
}