Go 指针

指针保存的是另一个变量的内存地址。两个运算符:& 取地址,* 解引用(通过地址读写变量)。(说明:文中的片段代码需放进完整程序里运行)

取地址与解引用

完整示例:

package main

import "fmt"

func main() {
	a := 10
	p := &a      // p 的类型是 *int,保存 a 的地址
	fmt.Println(p) // 打印地址,每次运行数值不同
	*p = 20      // 解引用:通过地址修改 a
	fmt.Println(a) // 20
}
// 输出:
// 0xc0000120a0
// 20

&变量 得到指针,*指针 得到它指向的变量,两者互为逆操作。

空指针 nil

指针的零值是 nil(空指针)。对 nil 解引用会 panic,使用前要判空:

var p *int
fmt.Println(p == nil) // true

if p != nil { // 判空后再解引用
	fmt.Println(*p)
}
a := 5
p = &a
fmt.Println(*p) // 5

指针参数:修改外部变量

普通参数按值传递,函数内改不动调用方的变量;传指针才能真正修改:

func swap(x, y *int) {
	*x, *y = *y, *x // 交换两个指针指向的值
}
// a, b := 3, 8; swap(&a, &b) → a=8, b=3

指针数组

数组元素可以是指针类型,即每个元素都指向一个变量:

x, y := 1, 2
ptrs := [2]*int{&x, &y} // 指针数组:元素类型是 *int
*ptrs[1] = 20            // 通过下标取到指针,再解引用修改 y
fmt.Println(x, y)        // 1 20

指向指针的指针(简述)

**int 是指向 *int 的指针,两层解引用才拿到最终变量,只在需要修改指针本身的场景使用:

a := 10
p := &a  // *int
pp := &p // **int
fmt.Println(**pp) // 10

与 C 语言的差异

  • Go 指针不能做算术运算p++p+1 非法(C 允许)。
  • Go 有垃圾回收,无需手动 free,没有悬垂指针崩溃问题。
  • 可以对局部变量取地址,编译器通过逃逸分析安全处理。
  • 指针类型不能随意转换,比 C 的强转安全得多。

小结:Go 指针比 C 安全——不能运算、有 GC 兜底。记住 & 取地址、* 解引用、先判空再用即可。

笔记加载中…