unsafe.pointer 與 uintptr的區別| 8月更文挑戰

unsafe.pointer與unintptr這兩個東西在源碼中出現的比較多,本身在業務上使用的比較少。可是面試中面試官仍是挺喜歡問的。面試

unsafe.pointer

從名字來看它是不安全的和指針相關,unsafer.pointer主要的功能就是不一樣類型指針間的轉換。安全

不一樣類型之間不能直接轉換markdown

func main() {
   var a *int8
   var b *int16
   a = new(int8)
   b = new(int16)
   *b = 10
   *a = *b
   fmt.Println(a)
}
複製代碼
  1. 初始化一個指針類型的int8 a
  2. 初始化一個指針類型的int16 b
  3. 給指針b指向的內存賦值10
  4. 指針a內存賦值指針b的內存值

結果:cannot use *b (type int16) as type int8 in assignment
go是強類型語言,這種即便都是int,這樣轉換也是不行的,因而出現了unsafe.pointer。svn

經過unsafe.pointer來花式轉換flex

var a *int8
var b *int16
a = new(int8)
b = new(int16)
*b = 10
upb := unsafe.Pointer(b)
b_int8ptr := (*int8)(upb)
*a = *(b_int8ptr)
fmt.Println(*a)
複製代碼
  1. 初始化一個指針類型的int8 a
  2. 初始化一個指針類型的int16 b
  3. 給指針b指向的內存賦值10
  4. 經過unsafe.pointer獲取b的指針upb
  5. 把upb轉成*int8指針 b_int8ptr
  6. 獲取b_int8ptr的內存值賦值給a的地址指向的空間

結果:10
unsafer.pointer能夠轉換不一樣類型的指針。ui

unintptr

uintptr 實際上就是一個 uint 用來表示地址的。url

var a, b uintptr
a = 10
b = 10
fmt.Println(a + b)
複製代碼

同類型的地址也不能直接相加spa

var a, b *int
a, b = new(int), new(int)
c:=a+b  //invalid operation: a + b (operator + not defined on pointer)
複製代碼

同類型的地址也不能直接相加指針

var a, b *int
a, b = new(int), new(int)
c := unsafe.Pointer(a) + unsafe.Pointer(b) // invalid operation: unsafe.Pointer(a) + unsafe.Pointer(b) (operator + not defined on unsafe.Pointer)
複製代碼

結合uintptr來作地址之間的運算code

var a, b *int
a, b = new(int), new(int)
c := uintptr(unsafe.Pointer(a)) + uintptr(unsafe.Pointer(b))
fmt.Println(c)
複製代碼

unsafe和uintptr的一些組合操做

type User struct {
   Name string
   Age  int8
}
func main() {
   u := &User{}
   uAddress := unsafe.Pointer(u)
   ageOffset := unsafe.Offsetof(u.Age)
   agePtr := unsafe.Pointer(uintptr(uAddress) + ageOffset)
   *((*int)(agePtr)) = 10
   fmt.Println(u.Age)
}
複製代碼
  1. 經過unsafe.Pointer獲取u的地址uAddress
  2. 經過unsafe.Offsetof獲取u.age的偏移量
  3. uintptr轉換uAddress 加上age的偏移量就找到了age的地址agePtr
  4. agePtr轉成指針型int,而後取其內存空間,賦值10

結合unsafe和uintptr也能夠對某些變量賦值,整個流程看下來比較複雜。

總結

  1. 任何類型的指針均可以被轉化爲Pointer
  2. Pointer能夠被轉化爲任何類型的指針
  3. uintptr能夠被轉化爲Pointer
  4. Pointer能夠被轉化爲uintptr
  5. unsafe.pointer是普通指針類型,用於轉換不一樣類型的指針,不能進行指針運算,不能讀取內存存儲的值,必須轉換到某一類型的普通指針。
  6. uintptr用於指針運算,GC不把uintptr當指針,uintptr沒法持有對象,uintptr類型的目標會被回收。
相關文章
相關標籤/搜索