小编典典

前言:

uintptruintptr
unsafe.Pointer

uintptr是整数,而不是引用。将Pointer转换为uintptr会创建一个没有指针语义的整数值。即使uintptr拥有某个对象的地址,垃圾回收器也不会在对象移动时更新该uintptr的值,该uintptr也不会使该对象被回收。

unsafe

reflect.SliceHeader
SliceHeader.DataSliceHeader.LenSliceHeader.Cap

完成此操作后,slice变量将指向与初始指针相同的数组。

arr := [10]byte{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}

size := len(arr)
p := uintptr(unsafe.Pointer(&arr))

var data []byte

sh := (*reflect.SliceHeader)(unsafe.Pointer(&data))
sh.Data = p
sh.Len = size
sh.Cap = size

fmt.Println(data)

runtime.KeepAlive(arr)

输出(在Go Playground上尝试):

[0 1 2 3 4 5 6 7 8 9]
runtime.KeepAlive()arrarrpuintptrarrdataarrruntime.KeepAlive()main()arrruntime.KeepAlive()
reflect.SliceHeader
sh := &reflect.SliceHeader{
    Data: p,
    Len:  size,
    Cap:  size,
}

data := *(*[]byte)(unsafe.Pointer(sh))

fmt.Println(data)

runtime.KeepAlive(arr)

输出将是相同的。在Go Playground上尝试一下。

unsafe.Pointer
var s string
hdr := (*reflect.StringHeader)(unsafe.Pointer(&s)) // case 1
hdr.Data = uintptr(unsafe.Pointer(p))              // case 6 (this case)
hdr.Len = n
// INVALID: a directly-declared header will not hold Data as a