指针类型

在正式介绍 unsafe 包之前,需要着重介绍 Go 语言中的指针类型。

我本科开始学编程的时候,第一门语言就是 C。之后又陆续学过 C++,Java,Python,这些语言都挺强大的,但是没了 C 语言那么“单纯”。直到我开始接触 Go 语言,又找到了那种感觉。Go 语言的作者之一 Ken Thompson 也是 C 语言的作者。所以,Go 可以看作 C 系语言,它的很多特性都和 C 类似,指针就是其中之一。
然而,Go 语言的指针相比 C 的指针有很多限制。这当然是为了安全考虑,要知道像 Java/Python 这些现代语言,生怕程序员出错,哪有什么指针(这里指的是显式的指针)?更别说像 C/C++ 还需要程序员自己清理“垃圾”。所以对于 Go 来说,有指针已经很不错了,仅管它有很多限制。

  1. package main
  2. import "fmt"
  3. func add(x int) {
  4. x+=x
  5. }
  6. func main() {
  7. var a=5
  8. add(a)
  9. fmt.Println(a) // 5
  10. }

非常简单,我想在add()函数里将变量a翻倍,但是例子中的函数却做不到。为什么?因为Go语言中的函数传参都是值传递。add()函数里的形参x只是实参a的一份值拷贝,在函数内部对x的操作不能反馈到实参a上。

然而,相比于 C 语言中指针的灵活,Go 的指针多了一些限制。但这也算是 Go 的成功之处:既可以享受指针带来的便利,又避免了指针的危险性。

限制一:Go语言指针不能运算

  1. a:=5
  2. p:=&a
  3. p++ //invalid operation: p++ (non-numeric type *int)
  4. p=&a+3 //invalid operation: &a + 3 (mismatched types *int and int)

unsafe 实现原理

我们来看源码:

  1. type ArbitraryType int
  2. type Pointer *ArbitraryType

从命名来看,Arbitrary 是任意的意思,也就是说 Pointer 可以指向任意类型,实际上它类似于 C 语言里的 void*

https://zhuanlan.zhihu.com/p/67852800