unsafe.Pointer/uintptr

  • unsafe.Pointer只是单纯的通用指针类型,任何类型的指针值都可以转换为 Pointer,Pointer 也可以转换为任何类型的指针值。但它不可以参与指针运算
  • uintptr 无符号整数uint64,是Go 的内置类型,用于指针运算的
  • unsafe.Pointer 可以和 uintptr 进行相互转换

注意,

  • GC 并不把 uintptr 当指针,也就是说 uintptr 无法持有对象, 如果目标对象经过uintptr转换之后没有其它的引用了,会被GC(不过由于GC延迟机制,不再被使用的内存块的回收时间 是 不确定的)
  • 但如果是unsafe.Pointer 指向了一个对象,那么 go 的 GC 会知道有这个对象,并不会释放这个对象的内存。

string 和 []byte 零拷贝转换

type SliceHeader struct {
	Data uintptr
	Len  int
	Cap  int
}
type StringHeader struct {
	Data uintptr
	Len  int
}

对比string和slice的数据结构,通过共享底层 []byte 数组、然后浅拷贝构造header,就可以实现零拷贝转换

func string2bytes(s string) []byte {
	stringHeader := (*reflect.StringHeader)(unsafe.Pointer(&s))

	bh := reflect.SliceHeader{
		Data: stringHeader.Data,
		Len: stringHeader.Len,
		Cap: stringHeader.Len,
	}

	return *(*[]byte)(unsafe.Pointer(&bh))
}

func bytes2string(b []byte) string {
	sliceHeader := (*reflect.SliceHeader)(unsafe.Pointer(&b))

	sh := reflect.StringHeader{
		Data: sliceHeader.Data,
		Len:  sliceHeader.Len,
	}

	return *(*string)(unsafe.Pointer(&sh))
}
posted @ 2024-02-17 22:59  LdreamerD  阅读(39)  评论(0)    收藏  举报