go语言的指针类型分为三种:
(1)普通指针类型:*类型,用于存储地址,不能进行指针运算
(2)通用指针类型:用于转换不同类型的指针,不能进行指针运算
(3)uintptr:用于指针运算,GC不把uintptr当指针,uintptr无法持有对象。uintptr对象会被回收。
unsafe.Pointer 可以和普通指针进行转换。
unsafe.Pointer 可以和 uintptr 进行相互转换。
也可以说 unsafe.Pointer 是桥梁,可以让任意类型的指针实现相互转换,也可以将任意类型的指针转换为uintptr进行指针运算。
package mainimport ( "fmt" "unsafe")func main() { s := struct { i int b bool str string }{1, true, "hello"} fmt.Println("原来s变量的内容为:", s) // 转换成通用指针 p := unsafe.Pointer(&s) // 转换成uintpre类型 up0 := uintptr(p) // 将uintpre类型转换成int指针类型 pi := (*int)(p) *pi = 10 fmt.Println(s) // 偏移到结构体下标b位置,p1类型为uintptr p1 := up0 + unsafe.Offsetof(s.b) // 将uintptr转化成通用指针 p = unsafe.Pointer(p1) // 将通用指针类型转化成bool指针类型 pb := (*bool)(p) *pb = false fmt.Println(s) // 偏移到结构体下标str位置,p2类型为uintptr p2 := up0 + unsafe.Offsetof(s.str) // 将uintptr类型转化成通用类型指针 p = unsafe.Pointer(p2) // 将通用指针类型转换成string指针类型 ps := (*string)(p) *ps = "hello world" fmt.Println(s) }
结构体成员的内存分配是连续的,第一个成员的地址就是结构体的地址,相对结构体的偏移量为0。其他成员都可以通过偏移量来计算其地址。
每种类型都有它的大小和对齐值,可以通过unsafe.Sizeof获取其大小,通常unsafe.Alignof获取其对齐值,通过unsafe.Offsetof获取其偏移量。不过unsafe.Alignof获取到的对齐值只是该类型单独使用时的对齐值,不是作为结构体字段时与其它对象间的对齐值,这里用不上,所以需要用unsafe.Offsetof来获取字段的偏移量,进而确定其内存地址。
package mainimport ( "fmt" "unsafe")func main() { s := struct { i int b bool str string }{1, true, "hello"} fmt.Println("s变量内容:", s) fmt.Println("变量s的大小:", unsafe.Sizeof(s)) fmt.Println("s.i的大小:", unsafe.Sizeof(s.i)) fmt.Println("s.b的大小:", unsafe.Sizeof(s.b)) fmt.Println("s.str的大小:", unsafe.Sizeof(s.str)) fmt.Println("-------------------------------") fmt.Println("s.i的偏移量:", unsafe.Offsetof(s.i)) fmt.Println("s.b的偏移量:", unsafe.Offsetof(s.b)) fmt.Println("s.str的偏移量:", unsafe.Offsetof(s.str)) fmt.Println("-------------------------------") fmt.Println("变量s的对齐:", unsafe.Alignof(s)) fmt.Println("s.i的对齐:", unsafe.Alignof(s.i)) fmt.Println("s.b的对齐:", unsafe.Alignof(s.b)) fmt.Println("s.str的对齐:", unsafe.Alignof(s.str)) }
作者:laijh
链接:https://www.jianshu.com/p/bd95d1548756
x
点击查看更多内容
为 TA 点赞
评论
共同学习,写下你的评论
评论加载中...
作者其他优质文章
正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦