unsafe.pointer与unintptr这两个东西在源码中出现的比较多,自己在业务上使用的比较少。但是面试中面试官还是挺喜欢问的。
从名字来看它是不安全的和指针相关,unsafer.pointer主要的功能就是不同类型指针间的转换。
不同类型之间不能直接转换
func main() {
var a *int8
var b *int16
a = new(int8)
b = new(int16)
*b = 10
*a = *b
fmt.Println(a)
}
复制代码
结果:cannot use *b (type int16) as type int8 in assignment
go是强类型语言,这种即使都是int,这样转换也是不行的,于是出现了unsafe.pointer。
通过unsafe.pointer来花式转换
var a *int8
var b *int16
a = new(int8)
b = new(int16)
*b = 10
upb := unsafe.Pointer(b)
b_int8ptr := (*int8)(upb)
*a = *(b_int8ptr)
fmt.Println(*a)
复制代码
upb
b_int8ptr
结果:10
unsafer.pointer可以转换不同类型的指针。
uintptr 实际上就是一个 uint 用来表示地址的。
var a, b uintptr
a = 10
b = 10
fmt.Println(a + b)
复制代码
同类型的地址也不能直接相加
var a, b *int
a, b = new(int), new(int)
c:=a+b //invalid operation: a + b (operator + not defined on pointer)
复制代码
同类型的地址也不能直接相加
var a, b *int
a, b = new(int), new(int)
c := unsafe.Pointer(a) + unsafe.Pointer(b) // invalid operation: unsafe.Pointer(a) + unsafe.Pointer(b) (operator + not defined on unsafe.Pointer)
复制代码
结合uintptr来做地址之间的运算
var a, b *int
a, b = new(int), new(int)
c := uintptr(unsafe.Pointer(a)) + uintptr(unsafe.Pointer(b))
fmt.Println(c)
复制代码
type User struct {
Name string
Age int8
}
func main() {
u := &User{}
uAddress := unsafe.Pointer(u)
ageOffset := unsafe.Offsetof(u.Age)
agePtr := unsafe.Pointer(uintptr(uAddress) + ageOffset)
*((*int)(agePtr)) = 10
fmt.Println(u.Age)
}
复制代码
结合unsafe和uintptr也可以对某些变量赋值,整个流程看下来比较复杂。
作者:假装懂编程
链接:https://juejin.cn/post/6991438499958243335
原文:https://www.cnblogs.com/maomaomaoge/p/15096430.html