以一个例子来讲明:ui
//misc.go指针
package misc type S struct { i int32 k int8 j int64 }
//main.gocode
func main() { s := new(misc.S) //经过unsafe Pointer给未导出的字段赋值 //由于字节对齐,内存中实际分配 //int32|int8| int64 | //|xxxx|x---|xxxxxxxx| p := (*int32)(unsafe.Pointer(s)) *p = int32(10) // 1.unsafe Pointer和uintptr能够互相转换 // 2.unsafe Pointer和其余类型的指针能够互相转换 // 3.unsafe Pointer不能进行指针运算而uintptr能 p1 := (*int8)(unsafe.Pointer(uintptr(unsafe.Pointer(s)) + unsafe.Alignof(int32(0))))//偏移4 *p1 = int8(-128) p2 := (*int64)(unsafe.Pointer(uintptr(unsafe.Pointer(s)) + unsafe.Alignof(s)))//偏移8 *p2 = int64(128) fmt.Println(s)//&{10 -128 128} fmt.Println(unsafe.Sizeof(*s))//16 由于字节对齐的缘故不是13 fmt.Println(unsafe.Sizeof(s))//8 s是指针,在64位系统里指针占8个字节,指针就是内存地址,大小跟系统有关跟语言无关 fmt.Println(unsafe.Alignof(s))//8 Alignof返回该类型的对齐值,struct的对齐值是成员类型对齐值的最大值 }
此例子基于struct在内存中是连续的,而且知道S的结构。以上仅为记录unsafe包的基本使用方式和字节对齐是怎么回事,以避免忘了,非实际应用场景。内存