Go的unsafe包
常規的Go程式碼是可以跨平臺的,因為常規程式碼只關心使用哪種資料結構,而不關心資料結構的內部實現,內部實現細節由編譯器處理。
而unsafe
這個包就是用來訪問內部實現細節的。所以,使用了unsafe這個包的程式碼,因為Go的編譯器實現細節改變,很有可能會造成相容性問題。
三個函式
unsafe
主要提供了三個函式:
Alignof Offsetof Sizeof
看示例:
package main import ( "fmt" "unsafe" ) type Demo struct { sstring iint ffloat64 bs []byte } func main() { d := Demo{} fmt.Println("Alignof:") fmt.Println(unsafe.Alignof(d.s)) fmt.Println(unsafe.Alignof(d.i)) fmt.Println(unsafe.Alignof(d.f)) fmt.Println(unsafe.Alignof(d.bs)) fmt.Println("Offsetof:") fmt.Println(unsafe.Offsetof(d.s)) fmt.Println(unsafe.Offsetof(d.i)) fmt.Println(unsafe.Offsetof(d.f)) fmt.Println(unsafe.Offsetof(d.bs)) fmt.Println("Sizeof:") fmt.Println(unsafe.Sizeof(d.s)) fmt.Println(unsafe.Sizeof(d.i)) fmt.Println(unsafe.Sizeof(d.f)) fmt.Println(unsafe.Sizeof(d.bs)) }
執行結果:
$ go run main.go Alignof: 8 8 8 8 Offsetof: 0 16 24 32 Sizeof: 16 8 8 24
unsafe.Pointer
這個型別相當於C語言裡的void *
。舉個例子,如果想把[]byte
轉換成 string 或者反之,該怎麼做呢?看看fasthttp裡的一段程式碼:
// b2s converts byte slice to a string without memory allocation. // See https://groups.google.com/forum/#!msg/Golang-Nuts/ENgbUzYvCuU/90yGx7GUAgAJ . // // Note it may break if string and/or slice header will change // in the future go versions. func b2s(b []byte) string { return *(*string)(unsafe.Pointer(&b)) } // s2b converts string to a byte slice without memory allocation. // // Note it may break if string and/or slice header will change // in the future go versions. func s2b(s string) []byte { sh := (*reflect.StringHeader)(unsafe.Pointer(&s)) bh := reflect.SliceHeader{ Data: sh.Data, Len:sh.Len, Cap:sh.Len, } return *(*[]byte)(unsafe.Pointer(&bh)) }