Go的unsafe包 - Go语言中文社区

Go的unsafe包


Go官方包提供了一个unsafe包,在这个包里面有含够绕开Go程序类型安全的操作。 既然是unsafe包,使用起来一定要特别小心。尽管unsafe有点危险,但是它也难以置信的有用。

unsafe的操作:

  1. A pointer value of any type can be converted to a Pointer.
  2. A Pointer can be converted to a pointer value of any type.
  3. A uintptr can be converted to a Pointer.
  4. A Pointer can be converted to a uintptr.

注意区别一般类型指针与unsafe指针。unsafe.Pointer类型指针能够覆盖Go类型系统。一个uintptr能够被转化为一个unsafe.Pointer类型,反之也一样。任何类型的指针能够转化为一个unsafe.Pointer指针。

运算

简单转化操作:

// unsafe.Pointer to a pointer to an integer.  
(* int)(unsafePtr)

// Pointer to an integer to an unsafe.Pointer
unsafe.Pointer(intPtr)

// unsafe.Pointer to a uintptr
uintptr(unsafePtr)

// uintptr to unsafe.Pointer
unsafe.Pointer(unsignedIntVar)

// uintptr to a pointer to an integer
(* int)(unsafe.Pointer(unsignedIntVar))

// pointer to an integer to a uintptr
uintptr(unsafe.Pointer(intPtr)) 

下面的实例就是一个运算操作 –指针偏移。

intArray := [...]int{10, 20}

fmt.Printf("nintArray: %vn", intArray)

intPtr := &intArray[0]
fmt.Printf("nintPtr=%p, *intPtr=%d.n", intPtr, *intPtr)

nextIntPtr := uintptr(unsafe.Pointer(intPtr)) + unsafe.Sizeof(intArray[0])

intPtr = (*int)(unsafe.Pointer(nextIntPtr))

fmt.Printf("nintPtr=%p, *intPtr=%d.nn", intPtr, *intPtr)

上面代码中,我们展示了unsafe.Pointer可以转化为任意类型的指针。

nextIntPtr := uintptr(unsafe.Pointer(intPtr)) + unsafe.Sizeof(intArray[0])

上面代码,uintptr的变量nextIntPtr定义为intPtr指针点下移一个数组元素空间大小unsafe.Sizeof(intArray[0])。即当前元素的地址位置下移到下一个元素位置上。

类型转化

下面例子说明了如何利用将unsafe.Pointer不同的变量指向同一个地址。

type MyStr string

a := []MyStr{"10", "100", "1000"}
// b := ([]MyStr)(a) // error: cannot convert a (type []MyStr) to type []MyStr
b := *(*[]MyStr)(unsafe.Pointer(&a))

b[0]= "0"

fmt.Println("a =", a) // a = [0 100 1000]
fmt.Println("b =", b) // b = [0 100 1000]

a[2] = "CONVERT"

fmt.Println("a =", a) // a = [0 100 CONVERT]
fmt.Println("b =", b) // b = [0 100 CONVERT]

总结

  • unsafe包服务于Go编译器而不是Go运行环境。
  • 使用unsafe命名这个包名,说明使用这个包的时候需要特别小心。
  • unsafe.Pointer不总是一个糟糕的主意,有时候,我们必须使用它。
  • unsafe包可能会被误用,其结果导致危险的境地。

欢迎加入我的微信公众号

欢迎加入我的微信公众号

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/GreatElite/article/details/78870765
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2019-08-27 15:46:37
  • 阅读 ( 924 )
  • 分类:Go

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢