
在 Go 中,& 是取地址运算符,用于获取变量的内存地址;* 则具有双重角色:一是声明指针类型(如 *int),二是解引用指针以访问其指向的值。二者协同实现内存间接访问,但语义和使用场景截然不同。
在 go 中,`&` 是取地址运算符,用于获取变量的内存地址;`*` 则具有双重角色:一是声明指针类型(如 `*int`),二是解引用指针以访问其指向的值。二者协同实现内存间接访问,但语义和使用场景截然不同。
Go 语言通过 & 和 * 构建了简洁而严谨的指针机制,但初学者常因二者符号相似而混淆。关键在于理解:*& 总是“生成地址”,`` 总是“关联地址”——或用于定义“能存地址”的类型,或用于“从地址读取值”。**
✅ &:取地址运算符(Address-of Operator)
&x 表示“变量 x 在内存中的地址”,结果是一个指针值(如 *int 类型)。它不改变原变量,仅提供其位置信息。
age := 28
addr := &age // addr 的类型是 *int,值为 age 的内存地址
fmt.Printf("%p\n", addr) // 输出类似 0xc0000140b0⚠️ 注意:& 只能作用于可寻址的值(如变量、结构体字段、切片元素),不能对字面量、函数调用结果或常量取地址,例如 &42 或 &len(arr) 是非法的。
✅ *:双重语义——类型声明 vs 解引用(Dereferencing)
* 在两个上下文中出现,意义完全不同:
立即学习“go语言免费学习笔记(深入)”;
| 场景 | 语法示例 | 含义 | 类型/结果 |
|---|---|---|---|
| 类型声明 | var p *string 或 p := &name | 声明 p 是一个“指向字符串的指针”类型 | p 的类型是 *string |
| 解引用操作 | *p | 获取 p 所指向内存地址中存储的实际值 | 类型是 string(即 p 的基类型) |
name := "Alice" p := &name // p 是 *string 类型,保存 name 的地址 fmt.Println(p) // 输出地址(如 0xc000016240) fmt.Println(*p) // 输出 "Alice" —— *p 解引用,读取该地址的值 *p = "Bob" // ✅ 合法:通过指针修改原值 fmt.Println(name) // 输出 "Bob"
? 完整工作流示例:声明 → 取址 → 解引用 → 修改
package main
import "fmt"
func main() {
count := 100
// 1. 声明指针变量(*int 表示“指向 int 的指针”类型)
var ptr *int
// 2. 使用 & 获取 count 的地址并赋值给 ptr
ptr = &count
// 3. 使用 *ptr 访问(读取)count 的值
fmt.Printf("Original value: %d\n", *ptr) // 100
// 4. 使用 *ptr 修改 count 的值(间接赋值)
*ptr = 200
fmt.Printf("Modified value: %d\n", count) // 200
}? 关键总结
- &x 是一元运算符,永远返回 x 的地址,类型为 *T(其中 T 是 x 的类型);
- *T 是类型表达式,表示“指向类型 T 的指针”(用于变量声明、函数参数、结构体字段等);
- *p 是一元解引用操作,要求 p 必须是合法指针(非 nil),否则运行时 panic;
- 没有“指针算术”(如 p++)、不支持指针类型转换(除非 unsafe),Go 的指针设计强调安全性与简洁性。
掌握 & 与 * 的分工,是理解 Go 内存模型、函数参数传递(尤其是传指针避免拷贝)、以及 new/make 等内置函数行为的基础。


















