5. 指针
指针是 Go 语言中又一重要的语言特性和数据类型,简单来说,指针即某个值的地址,在其他的高级语言,如 C/C++ 中也存在着指针的概念,但相比较 C/C++ 中的指针,Go 语言中的指针的设计是保留指针的高性能的同时,降低指针在致用过程中的复杂度。
5.1. 指针的概念
指针在 Go 语言中是一种数据类型,表示的是某个值的地址,使用 * 定义,同时使用 & 来获取变量的地址,如下代码所示:
func main() {
a := 6
var p *int = &a
fmt.Println(p) // 0x27765502c008
}
上述代码先定义一个整型变量 a,再定义一个整型的指针 p,该指针指向变量 a,通过 & 获取变量 a 的地址,其示意图如下所示:

除了上述直接指向一个变量,还可以直接声明指针,如下代码:
func main() {
var p *int
fmt.Println(p) // <nil>
}
指针的默认值都是 nil,表示空指针。另外,也可以使用 new() 函数初始化一个指针,代码如下:
func main() {
p := new(int)
fmt.Println(p)
}
你会发现通过 new() 函数初始化出来的指针并不是一个空指针。
5.2. 指针的使用场景
5.2.1. 改变变量的值
此时指针 p 指向的是变量 a 存储的位置,要想修改变量 a 的值,仅需要使用 * 对指针 p 解引用即可,代码如下:
func main() {
a := 6
var p *int = &a
// 修改变量 a 的值
*p = 7
fmt.Println(a) // 7
}
5.2.2. 作为函数的入参
函数的概念将在后续的章节中详细介绍到,现在只需要了解函数的概念,函数就是一段特定功能的代码,如实现加法的函数 add,代码如下:
func add(a int, b int) int {
return a+b
}
函数 add 的输入(也称为入参)为整形的 a 和 b,输出(也称为出参)也是整型,上述便是一个基本的函数的形式,要想调用函数,则有如下的代码:
func main() {
a := 1
b := 2
c := add(a, b)
fmt.Println(c)
}
现在要想实现整型 a 和 b 两个数的交换,我们该怎么做呢?想到的是直接交换,直接上代码,如下:
func exchange(a int, b int) {
tmp := a
a = b
b = tmp
}
func main() {
a := 1
b := 2
fmt.Println(a, b)
exchange(a, b)
fmt.Println(a, b)
}
我们发现整型变量 a 和 b 的值并没有改变。因为入参中只是整型变量 a 和 b 的副本,在函数 exchange 中的整型变量 a 和 b 的值是改变,如下代码所示:
func exchange(a int, b int) {
fmt.Println("in func: before -> ", a, b)
tmp := a
a = b
b = tmp
fmt.Println("in func: after -> ", a, b)
}
func main() {
a := 1
b := 2
fmt.Println(a, b)
exchange(a, b)
fmt.Println(a, b)
}
程序运行后输出的结果为:
1 2
in func: before -> 1 2
in func: after -> 2 1
1 2
我们发现在函数 exchange 中,整型变量 a 和 b 的值是改变了,那有什么办法交换真实的整型变量 a 和 b 呢?可以使用指针,代码如下:
func exchange(a *int, b *int) {
tmp := *a
*a = *b // 改变指针 a 指向变量的值
*b = tmp // 改变指针 b 指向变量的值
}
func main() {
a := 1
b := 2
fmt.Println(a, b)
exchange(&a, &b)
fmt.Println(a, b)
}
程序运行后输出的结果为:
1 2
2 1
在调用函数 exchange() 时,输入的入参是整型变量 a 和 b 的地址,在函数 exchange() 中,改变的是指针指向的变量的值,而不再是副本,也就是指针本身。
5.3. 与 C/C++ 中指针的对比
与 C/C++ 中指针相比,Go 语言中支持的指针相关的操作包括:
- 取地址,如通过取地址运算符
&取到变量的地址 - 解引用,如通过运算符
*取到指针指向的变量的值
除了上述基本的操作外,Go 语言中不支持的操作包括:
- 指针的运算
- 无需手动释放内存
- 在 Go 语言中,空指针为
nil
5.4. 本章小结
指针为 Go 语言的操作带来了便利,方便直接对内存中变量的修改,同时在函数传参的过程中,通过传入指针,可以方便的修改原始的参数。同时,在 Go 语言中也删除了指针的复杂操作,如指针的运算,无需手动释放内存等。