
本文深入讲解 Go 语言中 &(取地址)和 *(解引用/指针类型标识)的核心语义,厘清它们在变量使用、函数签名及返回值中的不同角色,并通过可运行示例阐明常见误用场景。
本文深入讲解 go 语言中 `&`(取地址)和 `*`(解引用/指针类型标识)的核心语义,厘清它们在变量使用、函数签名及返回值中的不同角色,并通过可运行示例阐明常见误用场景。
在 Go 中,& 和 * 是指针机制的两大基石,但它们的含义高度依赖上下文——既可能是运算符,也可能是类型构成的一部分。理解这一点,是掌握 Go 内存模型与高效编程的关键。
一、&:取地址运算符(Address-of Operator)
& 作用于一个已存在的变量,返回其在内存中的地址,结果是一个指针值。它不改变原变量,仅生成指向它的“路标”。
name := "Alice"
addr := &name // addr 的类型是 *string,值为 name 的内存地址
fmt.Printf("%p\n", addr) // 输出类似 0xc000010230
⚠️ 注意:& 后必须跟一个可寻址的变量(如命名变量、结构体字段、切片元素),不能对字面量或临时值取地址:
// ❌ 错误:无法对字符串字面量取地址 // badPtr := &"hello" // 编译错误 // ✅ 正确:先声明变量,再取地址 s := "hello" goodPtr := &s
二、* 的双重身份:解引用运算符 vs 指针类型标识
这是 Go 中最易混淆的设计——同一个符号 * 在不同位置承担完全不同的语法职责:
✅ 场景 1:* 作为解引用运算符(前缀操作符)
作用于一个指针变量,获取其所指向的值(即“解开指针”):
age := 42 ptr := &age // ptr 类型为 *int value := *ptr // value == 42,类型为 int *ptr = 99 // 修改原变量 age 的值为 99 fmt.Println(age) // 输出 99
✅ 场景 2:* 作为指针类型声明的一部分
出现在类型名前(如 *int, *Person, *[]string),表示“该类型是一个指向某类型的指针”。它定义的是变量或参数的类型,而非执行操作:
func processAge(ptr *int) { // ptr 是 *int 类型(指向 int 的指针)
*ptr *= 2 // 解引用并修改
}
age := 25
processAge(&age) // 传入 age 的地址
fmt.Println(age) // 输出 50
? 关键区别:*T 是类型;*x 是表达式(解引用)。编译器通过语法位置自动区分。
三、回到你的代码片段:澄清常见误解
你提供的示例代码存在多处语法错误(如 func1.newfunc[]、addtother 未定义等),并非合法 Go 代码,因此不能直接运行。但其中涉及的 * 和 & 用法可对照上述规则分析:
第 1 行伪代码 ... *callproperfunction
→ 表示该函数返回一个 *callproperfunction 类型的值,即“指向 callproperfunction 类型实例的指针”。第 7 行伪代码 return &callproperfunction {...}
→ & 是取地址运算符,对结构体字面量取地址,生成一个指向新分配结构体的指针,类型恰好匹配 *callproperfunction。
✅ 正确的 Go 实现应类似:
type CallProperFunction struct {
Var1 int
Var2 int
Jackpot bool
}
func initial1(v1, v2 int) *CallProperFunction {
return &CallProperFunction{Var1: v1, Var2: v2, Jackpot: v1 > v2}
}
四、为什么用指针?实用价值总结
- 避免大对象拷贝:传递 *LargeStruct 比传递 LargeStruct 更高效;
- 允许函数修改调用方数据:通过 *int 参数可修改原始整数;
- 实现可变的 slice/map/channel(因它们本身已是引用类型,但指针仍用于特殊场景,如交换 map 引用);
- 满足接口或方法集要求:某些方法只定义在指针接收者上(如 func (p *Person) Save())。
? 提示:Go 不支持指针算术(如 ptr++)、也不支持多重间接(如 **int 需显式解引用两次),这大幅降低了指针误用风险,使指针更安全、更易推理。
掌握 & 与 * 的上下文语义,你就掌握了 Go 指针的全部逻辑——它不是 C++ 的简化版,而是一套为清晰性与安全性重新设计的轻量级内存抽象。











