先说结论
- uintptr 是一个地址数值,它不是指针,与地址上的对象没有引用关系,垃圾回收器不会因为有一个uintptr类型的值指向某对象而不回收该对象。
- unsafe.Pointer是一个指针,类似于C的
void *
,它与地址上的对象存在引用关系,垃圾回收器会因为有一个unsafe.Pointer类型的值指向某对象而不回收该对象。 - 任何指针都可以转为unsafe.Pointer
- unsafe.Pointer可以转为任何指针
- uintptr可以转换为unsafe.Pointer
- unsafe.Pointer可以转换为uintptr
- 指针不能直接转换为uintptr
为什么需要uintptr这个类型呢?
理论上说指针不过是一个数值,即一个uint,但实际上在go中unsafe.Pointer是不能通过强制类型转换为一个uint的,只能将unsafe.Pointer强制类型转换为一个uintptr。
代码语言:javascript复制var v1 float64 = 1.1
var v2 *float64 = &v1
_ = int(v2) // 这里编译报错:cannot convert unsafe.Pointer(v2) (type unsafe.Pointer) to type uint
但是可以将一个unsafe.Pointer强制类型转换为一个uintptr:
代码语言:javascript复制var v1 float64 = 1.1
var v2 *float64 = &v1
var v3 uintptr = uintptr(unsafe.Pointer(v2))
v4 := uint(v3)
fmt.Println(v3, v4) // v3和v4打印出来的值是相同的
可以理解为uintptr是专门用来指针操作的uint。 另外需要指出的是指针不能直接转为uintptr,即
代码语言:javascript复制var a float64
uintptr(&a) 这里会报错,不允许将*float64转为uintptr