image
問題
能說說uintptr和unsafe.Pointer的區(qū)別嗎耘眨?
怎么答
- unsafe.Pointer只是單純的通用指針類型,用于轉(zhuǎn)換不同類型指針境肾,它不可以參與指針運(yùn)算剔难;
- 而uintptr是用于指針運(yùn)算的,GC 不把 uintptr 當(dāng)指針奥喻,也就是說 uintptr 無法持有對象偶宫, uintptr 類型的目標(biāo)會被回收;
- unsafe.Pointer 可以和 普通指針 進(jìn)行相互轉(zhuǎn)換环鲤;
- unsafe.Pointer 可以和 uintptr 進(jìn)行相互轉(zhuǎn)換纯趋。
舉例
- 通過一個(gè)例子加深理解,接下來嘗試用指針的方式給結(jié)構(gòu)體賦值冷离。
package main
import (
"fmt"
"unsafe"
)
type W struct {
b int32
c int64
}
func main() {
var w *W = new(W)
//這時(shí)w的變量打印出來都是默認(rèn)值0吵冒,0
fmt.Println(w.b,w.c)
//現(xiàn)在我們通過指針運(yùn)算給b變量賦值為10
b := unsafe.Pointer(uintptr(unsafe.Pointer(w)) + unsafe.Offsetof(w.b))
*((*int)(b)) = 10
//此時(shí)結(jié)果就變成了10,0
fmt.Println(w.b,w.c)
}
-
uintptr(unsafe.Pointer(w))
獲取了w
的指針起始值
-
unsafe.Offsetof(w.b)
獲取b
變量的偏移量
- 兩個(gè)
相加
就得到了b
的地址值
西剥,將通用指針Pointer
轉(zhuǎn)換成具體指針((*int)(b))
痹栖,通過*
符號取值,然后賦值瞭空。*((*int)(b))
相當(dāng)于把(*int)(b)
轉(zhuǎn)換成int
了揪阿,最后對變量重新賦值成10
,這樣指針運(yùn)算就完成了咆畏。