这是我参与「第三届青训营 -后端场」笔记创作活动的的第4篇笔记
什么是指针类型和我们学过的所有类型都不同,指针类型是依托某一个类型而存在的,比如:一个整型为 int,那么它对应的整型指针就是 *int,也就是在 int 的前面加上一个星号。没有 int 类型,就不会有 *int 类型。而 int 也被称为 *int 指针类型的基类型。我们泛化一下指针类型的这个定义:如果我们拥有一个类型 T,那么以 T 作为基类型的指针类型为 *T。声明一个指针类型变量的语法与非指针类型的普通变量是一样的,我们以声明一个 *T 指针类型的变量为例 var p *T
不过 Go 中也有一种指针类型是例外,它不需要基类型,它就是 unsafe.Pointer。unsafe.Pointer 类似于 C 语言中的 void*,用于表示一个通用指针类型,也就是任何指针类型都可以显式转换为一个 unsafe.Pointer,而 unsafe.Pointer 也可以显式转换为任意指针类型,如下面代码所示:
var p *T var p1 = unsafe.Pointer(p) // 任意指针类型显式转换为unsafe.Pointer p = (*T)(p1) // unsafe.Pointer也可以显式转换为任意指针类型
unsafe.Pointer 是 Go 语言的高级特性,在 Go 运行时与 Go 标准库中 unsafe.Pointer 都有着广泛的应用。但 unsafe.Pointer 属于 unsafe 编程范畴,我这里就不深入了,你感兴趣可以查一下资料。如果指针类型变量没有被显式赋予初值,那么它的值为 nil var p *T println(p == nil) // true
那么,如果要给一个指针类型变量赋值,我们该怎么做呢?我们以一个整型指针类型为例来看一下:
var a int = 13 var p *int = &a // 给整型指针变量p赋初值
在这个例子中,我们用&a作为 *int 指针类型变量 p 的初值,这里变量 a 前面的&符号称为取地址符号,这一行的含义就是将变量 a 的地址赋值给指针变量 p。这里要注意,我们只能使用基类型变量的地址给对应的指针类型变量赋值,如果类型不匹配,Go 编译器是会报错的,比如下面这段代码var b byte = 10 var p *int = &b // Go编译器报错:cannot use &b (value of type *byte) as type *int in variable declaration
到这里,我们可以看到:指针类型变量的值与我们之前所了解的任何类型的值都不同