Go?指針、uintptr、unsafe.Pointer之間如何轉(zhuǎn)換
普通指針(*T)
普通指針類型,用于傳遞對象地址,不能進行指針運算
a := 10
var b *int //int類型指針
b = &a
fmt.Println("a=", a) // a=10
fmt.Println("b=", b) // b=0xc000225530 輸出的是a的地址
fmt.Println("c=", *b) // c=10 對a的地址進行取值
uintptr
uintptr是一個無符號的整型,它可以保存一個指針地址,它可以進行指針運算。想取值需要轉(zhuǎn)成unsafe.Pointer后, 需再轉(zhuǎn)到相對應(yīng)的指針類型。
源代碼中的定義如下。
package builtin //uintptr is an integer type that is large enough to hold the bit pattern of any pointer. //uintptr是一個能足夠容納指針位數(shù)大小的整數(shù)類型 type uintptr uintptr
unsafe.Pointer
unsafe.Pointer功能介紹

unsafe.Pointer定義如下,可以指向任意類型的int指針。不能進行指針運算,不能讀取內(nèi)存存儲的值(想讀取的話需要轉(zhuǎn)成相對應(yīng)類型的指針)。
它是橋梁,讓任意類型的指針實現(xiàn)相互轉(zhuǎn)換, 也可以轉(zhuǎn)換成uintptr 進行指針運算。
type Pointer *ArbitraryType type ArbitraryType int
unsafe.Pointer作為橋梁實現(xiàn)相互轉(zhuǎn)換

unsafe.Pointer在unsafe包中還有以下幾個函數(shù)在我們計算可能會用到
==unsafe包的幾個函數(shù)== //返回一個變量占用的內(nèi)存字節(jié)數(shù) func Sizeof(x ArbitraryType) uintptr //返回結(jié)構(gòu)體某個字段的地址相對于此結(jié)構(gòu)體起始地址的偏移量 func Offsetof(x ArbitraryType) uintptr //返回對齊系數(shù) func Alignof(x ArbitraryType) uintptr
指針和unsafe.Pointer的轉(zhuǎn)換
舉些栗子:
a := int64(100)
var ptr *int
ptr = (*int)(unsafe.Pointer(&a))
fmt.Printf("%d\n", *ptr)
//輸出100 如果是int32輸出一個很大值
這是個將int64轉(zhuǎn)換為int的場景,如果是int32的話轉(zhuǎn)換起來會出問題,因為存在轉(zhuǎn)換后的類型大于轉(zhuǎn)換前的類型。
如果是結(jié)構(gòu)體的話,我們可以用到unsafe.Offsetof函數(shù)來計算
type People struct {
age int32
height int64
}
var p = &People
height := unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Offsetof(p.height))
*((*int)(height)) = 100 //將height的值改為100
//uintptr(unsafe.Pointer(p)) 獲取了 w 的指針起始值
//unsafe.Offsetof(w.p) 獲取 b 變量的偏移量
uintptr和unsafe.Pointer的轉(zhuǎn)換
同樣舉個栗子,結(jié)合上面的People結(jié)構(gòu)體的操作,對unsafe.Pointer和uintptr的轉(zhuǎn)換做一個詳細的說明,對加深理解非常清晰明了。
var p = &People height := unsafe.Pointer(uintptr(unsafe.Pointer(p)) + unsafe.Offsetof(p.height)) *((*int)(height)) = 100 //將height的值改為100
上面的代碼可以理解為以下步驟:
- 要想修改People結(jié)構(gòu)體的height的值,首先unsafe.Pointer(p),轉(zhuǎn)換為uintptr
- 通過unsafe.Offsetof獲取height的偏移量,兩者都是uintptr,可進行運算得到height的地址
- unsafe.Pointer將height的地址轉(zhuǎn)為uintptr
- 先轉(zhuǎn)為*int指針,然后獲得height的值并賦值100
總結(jié)
指針、uintptr、unsafe.Pointer之間的轉(zhuǎn)換有點繞,相信看完這個會對這個有一個非常清晰的了解。大家可以動手試試
到此這篇關(guān)于Go 指針、uintptr、unsafe.Pointer之間如何轉(zhuǎn)換的文章就介紹到這了,更多相關(guān)Go 指針 uintptr unsafe.Pointer內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Go空結(jié)構(gòu)體struct{}的作用是什么
本文主要介紹了Go空結(jié)構(gòu)體struct{}的作用是什么,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-02-02
Golang時間及時間戳的獲取轉(zhuǎn)換超全面詳細講解
說實話,golang的時間轉(zhuǎn)化還是很麻煩的,最起碼比php麻煩很多,下面這篇文章主要給大家介紹了關(guān)于golang時間/時間戳的獲取與轉(zhuǎn)換的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-12-12
Golang try catch與錯誤處理的實現(xiàn)
社區(qū)不少人在談?wù)?nbsp;golang 為毛不用try/catch模式,而采用苛刻的recovery、panic、defer組合,本文就來詳細的介紹一下,感興趣的可以了解一下2021-07-07
Go 使用Unmarshal將json賦給struct出錯的原因及解決
這篇文章主要介紹了Go 使用Unmarshal將json賦給struct出錯的原因及解決方案,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2021-03-03

