Appearance
第 10 章:指针
10.1 什么是指针?指针的作用
指针是一个变量,它存储的是另一个变量的内存地址。指针的主要作用是:
- 传递大型数据结构时避免复制,提高性能
- 实现引用语义,允许函数修改调用者的变量
- 实现数据结构如链表、树等
10.2 指针定义与取值、取地址
定义指针
使用 * 符号定义指针类型:
go
var ptr *int // 定义一个指向 int 类型的指针取地址
使用 & 符号获取变量的地址:
go
var x int = 10
ptr := &x // ptr 现在指向 x 的地址取值
使用 * 符号获取指针指向的值:
go
var x int = 10
ptr := &x
fmt.Println(*ptr) // 输出 10示例
go
package main
import "fmt"
func main() {
var x int = 10
fmt.Println("x =", x)
fmt.Println("&x =", &x)
var ptr *int = &x
fmt.Println("ptr =", ptr)
fmt.Println("*ptr =", *ptr)
// 通过指针修改值
*ptr = 20
fmt.Println("After modifying through pointer:")
fmt.Println("x =", x)
fmt.Println("*ptr =", *ptr)
}10.3 指针与函数、指针与切片 / Map
指针与函数
通过指针,函数可以修改调用者的变量:
go
func increment(x *int) {
*x++
}
func main() {
var x int = 10
fmt.Println("Before:", x) // 输出 10
increment(&x)
fmt.Println("After:", x) // 输出 11
}指针与切片
切片本身就是引用类型,不需要使用指针:
go
func modifySlice(s []int) {
s[0] = 100
}
func main() {
s := []int{1, 2, 3}
fmt.Println("Before:", s) // 输出 [1 2 3]
modifySlice(s)
fmt.Println("After:", s) // 输出 [100 2 3]
}指针与 Map
Map 也是引用类型,不需要使用指针:
go
func modifyMap(m map[string]int) {
m["key"] = 100
}
func main() {
m := map[string]int{"key": 10}
fmt.Println("Before:", m) // 输出 map[key:10]
modifyMap(m)
fmt.Println("After:", m) // 输出 map[key:100]
}10.4 指针使用注意事项
1. 空指针
未初始化的指针是 nil,不能对 nil 指针进行取值操作:
go
var ptr *int
fmt.Println(ptr) // 输出 <nil>
// fmt.Println(*ptr) // 运行时错误:nil pointer dereference2. 指针的零值
指针的零值是 nil:
go
var ptr *int
if ptr == nil {
fmt.Println("ptr is nil")
}3. 指针的比较
可以比较两个指针是否指向同一个地址:
go
var x int = 10
ptr1 := &x
ptr2 := &x
fmt.Println(ptr1 == ptr2) // 输出 true
var y int = 10
ptr3 := &y
fmt.Println(ptr1 == ptr3) // 输出 false4. new 函数
使用 new 函数创建一个新的变量并返回其指针:
go
ptr := new(int) // 创建一个 int 类型的变量,返回其指针
*ptr = 10
fmt.Println(*ptr) // 输出 105. 指针数组
go
var x, y, z int = 1, 2, 3
arr := [3]*int{&x, &y, &z}
for _, p := range arr {
fmt.Println(*p)
}6. 指针的指针
go
var x int = 10
ptr := &x
pptr := &ptr
fmt.Println(**pptr) // 输出 10