在golang中,可以利用unsafe套件來實現指標轉換,實現記憶體位址在不同指標型之間的轉換,進而更靈活地操作記憶體。例如unsafe套件下的Pointer()函數可以將任意變數的位址轉換成Pointer類型,也可以將Pointer型別轉換成任意的指標類型,Pointer型別是不同指標型別之間互轉的中間型別。
本教學操作環境:windows7系統、GO 1.18版本、Dell G3電腦。
在golang中,可以利用unsafe套件來實現指標轉換。
golang的指標轉換
Golang 提供了 unsafe 包,讓我們可以直接操作指定記憶體位址的記憶體。
unsafe套件下,有定義type Pointer *ArbitraryType(任意型別指標),可繞過GO的型別限制,type ArbitraryType int
任何類型的指標值都可以轉換為Pointer。
Pointer可以轉換為任何類型的指標值。
uintptr可以轉換為Pointer。
Pointer可以轉換成uintptr。
透過 unsafe.Pointer() 函數,我們能夠取得變數的記憶體位址表示,本質上這是個整數。可以將任意變數的位址轉換成 Pointer 類型,也可以將 Pointer 類型轉換成任意的指標類型,它是不同指標類型之間互轉的中間類型。
但 Pointer 不支援運算,如果要在記憶體位址上進行加減運算,需要將其轉為 uintptr 類型。
下面我們嘗試讀取切片位址,並透過記憶體操作遍歷其內容:
package main import "fmt" import "unsafe" func main() { // head = {address, 10, 10} // body = [1,2,3,4,5,6,7,8,9,10] var s = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} var address = (**[10]int)(unsafe.Pointer(&s)) var len = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(8))) var cap = (*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) + uintptr(16))) fmt.Println(address, *len, *cap) var body = **address for i := 0; i < 10; i++ { fmt.Printf("%d ", body[i]) } } ---------- 0xc000004460 10 10 1 2 3 4 5 6 7 8 9 10
上述程式碼中:
unsafe.Pointer(&s) 取得切片s 底層表示的第一個位置的記憶體位址,也即底層陣列的位址存放位址,
透過(**[10]int)(unsafe .Pointer(&s)) 將其轉為**[10]int 類型指針,再透過**addrss 還原為數組;
unsafe.Pointer(uintptr(unsafe.Pointer( &s)) uintptr(8)) 透過位址運算,取得length 的存放位址,
#進而透過(*int)(unsafe.Pointer(uintptr(unsafe.Pointer(&s)) uintptr(8)))將length 記憶體轉為int 指標
最後透過*len 取得切片長度;
對於cap 的操作與len 類似,不再贅述;
#總之:
透過unsafe,我們能夠實現記憶體位址在不同指標型別間的轉換,進而更靈活地操作記憶體;
本實驗也進一步驗證了切片的底層儲存結構;
unsafe 在不是必須的條件下應該少使用,直接操作記憶體畢竟是風險較大的;
以上是golang怎麼實現指標轉換的詳細內容。更多資訊請關注PHP中文網其他相關文章!