在 Go 中,& 是取地址操作符,用于获取变量的内存地址;* 既用于声明指针类型(如 *int),也用于解引用指针(如 *p)以访问其所指向的值——二者语义相反、协同工作,是理解 Go 内存模型的基础。
在 go 中,`&` 是取地址操作符,用于获取变量的内存地址;`*` 既用于声明指针类型(如 `*int`),也用于解引用指针(如 `*p`)以访问其所指向的值——二者语义相反、协同工作,是理解 go 内存模型的基础。
Go 语言中的 & 和 * 是指针操作的核心符号,但功能截然不同,不可互换。准确理解它们的职责,是写出安全、高效 Go 代码的关键。
&:取地址操作符(Address-of Operator)
& 作用于一个已存在的变量,返回其在内存中的地址,结果是一个指针类型值。它不改变原变量,只提供“通往该变量的路径”。
age := 28 addr := &age // addr 的类型是 *int,值为 age 所在内存地址
*:双重角色——类型声明符 & 解引用操作符
* 在 Go 中有两种上下文用法,取决于它出现的位置:
-
在类型声明中(右侧):表示“指向某类型的指针”
var p *string // p 是一个指向 string 的指针(类型为 *string) var nums *[]int // nums 是一个指向切片的指针(类型为 *[]int)
-
在表达式中(前缀操作符):表示“解引用”,即通过指针访问其所指向的值
name := "Alice" p := &name // p 类型为 *string,存储 name 的地址 fmt.Println(*p) // 输出 "Alice" —— *p 就是 name 本身 *p = "Bob" // 修改 p 所指向的内存,等价于 name = "Bob" fmt.Println(name) // 输出 "Bob"
完整示例:声明、赋值与解引用全流程
package main
import "fmt"
func main() {
x := 42
// 1. 声明指针变量:*int 表示「指向 int 的指针」类型
var ptr *int
// 2. 取地址并赋值:&x 得到 x 的内存地址
ptr = &x
// 3. 解引用:*ptr 获取 ptr 所指向的值(即 x 的值)
fmt.Printf("x = %d\n", x) // x = 42
fmt.Printf("ptr points to address: %p\n", ptr) // 如 0xc0000140a0
fmt.Printf("*ptr = %d\n", *ptr) // *ptr = 42
// 4. 通过指针修改原值
*ptr = 99
fmt.Printf("x after *ptr = 99: %d\n", x) // x = 99
}
⚠️ 注意事项与常见误区
- *T 是类型,*t(当 t 是指针变量时)是表达式——语法位置决定语义;
- 对 nil 指针解引用(*nilPtr)会引发 panic:invalid memory address or nil pointer dereference;
- & 只能作用于可寻址的值(如变量、结构体字段、切片元素),不能对字面量或函数调用结果取地址(如 &42 或 &fmt.Sprintf("x") 是非法的);
- Go 没有指针运算(如 ptr++ 或 ptr + 1),不支持指针算术,增强了内存安全性。
掌握 & 与 * 的分工——& 出发,“建造桥梁”;* 到达,“通行取物”——你便真正掌握了 Go 指针的底层逻辑。它们不是冗余符号,而是同一枚硬币的两面:一个连接世界,一个抵达本质。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











