Skip to the content.

unsafe.Pointer 是什么

一个普通的*T类型指针可以被转化为unsafe.Pointer类型指针,并且一个unsafe.Pointer类型指针也可以被转回普通的指针,被转回普通的指针类型并不需要和原始的*T类型相同

1.用于类型转化

例如,把float64类型转化为unint64类型

func Float64bits(f float64) uint64 {
	return *(*uint64)(unsafe.Pointer(&f))
}

2.指针运算

再指针的基础上,通过操作指针地址实现成员变量的访问

func main() {
    data := []byte("abcd")
    for i := 0; i < len(data); i++ {
        ptr := unsafe.Pointer(uintptr(unsafe.Pointer(&data[0])) + uintptr(i)*unsafe.Sizeof(data[0])) 
        fmt.Printf("%c,", *(*byte)(unsafe.Pointer(ptr)))
    }
    fmt.Printf("\n")
}

结果:

a,b,c,d,

3.读写结构内部成员

string类型的定义

type stringStruct struct {
    str unsafe.Pointer
    len int
}

reflect.StringHeader 的定义

type StringHeader struct {
    Data uintptr
    Len  int
}

unsafe.Pointer与uintptr在内存结构上是相同的,可以相互转换

func main() {
    str1 := "hello world"
    hdr1 := (*reflect.StringHeader)(unsafe.Pointer(&str1)) // 注1
    fmt.Printf("str:%s, data addr:%d, len:%d\n", str1, hdr1.Data, hdr1.Len)

    str2 := "abc"
    hdr2 := (*reflect.StringHeader)(unsafe.Pointer(&str2))

    hdr1.Data = hdr2.Data // 注2
    hdr1.Len = hdr2.Len   // 注3
    fmt.Printf("str:%s, data addr:%d, len:%d\n", str1, hdr1.Data, hdr1.Len)
}

运行结果

str:hello world, data addr:15595488, len:11
str:abc, data addr:15591112, len:3

最后,str1的值,已经被修改成了str2的值,即”abc”。

总结