
在 Go 中,& 是取地址操作符,用于获取变量的内存地址;* 既有类型声明作用(定义指针类型),也有解引用作用(读取指针指向的值)——二者功能互补,不可互换。
在 go 中,`&` 是取地址操作符,用于获取变量的内存地址;`*` 既有类型声明作用(定义指针类型),也有解引用作用(读取指针指向的值)——二者功能互补,不可互换。
Go 语言中的 & 和 * 是指针机制的两个基石操作符,但语义和使用场景截然不同:*& 是“取地址”,而 `` 是“声明指针类型”或“解引用”**。理解它们的分工,是掌握 Go 内存模型与高效编程的关键。
&:取地址操作符(Address-of Operator)
& 作用于一个已存在的变量,返回其在内存中的地址(即指针值)。它不改变原变量,只生成一个指向它的指针:
x := 42 p := &x // p 的类型是 *int,值为 x 的内存地址
此时 p 是一个指针变量,保存的是 x 所在位置的地址。
*:双重角色——类型声明 vs. 解引用
* 在 Go 中有两种上下文用法,取决于它出现的位置:
立即学习“go语言免费学习笔记(深入)”;
-
*在类型声明中(如 `int)**:表示“指向int` 类型的指针”——这是类型的一部分,用于定义指针变量:
var p *int // 声明 p 为 *int 类型(即“int 指针”) p = &x // 此时才能赋值,因为 &x 的类型正是 *int
-
*在表达式中(如 `p`):表示解引用(dereference)**,即通过指针访问其所指向的值:
fmt.Println(*p) // 输出 42 —— 读取 p 指向的 int 值 *p = 100 // 修改 p 指向的值(即修改 x 的值为 100)
完整示例:声明、赋值与解引用全流程
package main
import "fmt"
func main() {
age := 28
// ① 使用 *int 声明指针变量
var agePtr *int
// ② 使用 & 取地址并赋值给指针
agePtr = &age
// ③ 使用 * 解引用:读取和修改
fmt.Printf("age 的地址: %p\n", agePtr) // 如 0xc0000140b0
fmt.Printf("age 的值: %d\n", *agePtr) // 输出 28
*agePtr = 29 // 修改 age 的值为 29
fmt.Printf("修改后 age = %d\n", age) // 输出 29
}注意事项与常见误区
- ❌ * 不能单独用于未声明的变量(如 *x 报错:invalid indirect of x (type int)),必须确保 x 是指针类型;
- ✅ & 只能作用于可寻址的值(如变量、结构体字段、切片元素),不能对字面量或函数调用结果取地址(如 &42 或 &len(s) 非法);
- ⚠️ 解引用空指针(nil)会触发 panic:panic: runtime error: invalid memory address or nil pointer dereference,使用前建议判空;
- ? 指针传递是 Go 实现“按引用语义”的主要方式(例如函数接收 *string 可修改原字符串内容),但 Go 本身始终是按值传递——传递的是指针的副本,而非变量本身。
掌握 & 和 * 的精准语义,不仅能写出更安全、高效的代码,也为理解 Go 的并发模型(如 sync.Pool)、内存布局及底层接口实现打下坚实基础。


















