unsafe库彷徨在“类型平安”边缘,因为它们绕过了 Golang 的内存平安准则,个别被认为应用该库是不平安的。然而,在许多状况下,unsafe库的作用又是不可代替的,灵便地应用它们能够实现对内存的间接读写操作。在reflect库、syscall库以及其余许多须要操作内存的开源我的项目中都有对它的援用。

unsafe库源码极少,只有两个类型的定义和三个办法的申明。

Pointer 类型

这个类型比拟重要,它是实现定位欲读写的内存的根底。官网文档对该类型有四个重要形容:
(1)任何类型的指针都能够被转化为 Pointer
(2)Pointer 能够被转化为任何类型的指针
(3)uintptr 能够被转化为 Pointer
(4)Pointer 能够被转化为 uintptr
举例来说,该类型能够这样应用:

func main() {     i := 100     fmt.Println(i) // 100     p := (*int)unsafe.Pointer(&i)     fmt.Println(*p) // 100     *p = 0     fmt.Println(i) // 0     fmt.Println(*p) // 0}

Sizeof 函数
该函数的定义如下:

func Offsetof(v ArbitraryType) uintptr

该函数返回由 v 所批示的某构造体中的字段在该构造体中的地位偏移字节数,留神,v 的表达方式必须是“ struct.filed ”模式。
举例说明,在 64 为零碎中运行以下代码:

type Datas struct{    c0 byte    c1 int    c2 string    c3 int}func main(){    var d Datas    fmt.Println(unsafe.Offset(d.c0)) // 0    fmt.Println(unsafe.Offset(d.c1)) // 8    fmt.Println(unsafe.Offset(d.c2)) // 16    fmt.Println(unsafe.Offset(d.c3)) // 32}

如果晓得的构造体的起始地址和字段的偏移值,就能够间接读写内存:

d.c3 = 13p := unsafe.Pointer(&d)offset := unsafe.Offsetof(d.c3)q := (*int)(unsafe.Pointer(uintptr(p) + offset))fmt.Println(*q) // 13*p = 1013fmt.Println(d.c3) // 1013