以一個例子來講明: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包的基本使用方式和字節對齊是怎麼回事,以避免忘了,非實際應用場景。內存