Go中用&取变量地址,指针类型为*T;不可对常量取地址,解引用需判空,函数传指针可修改原值,但小类型传值更安全,接口存nil指针时不为nil。

如何获取变量地址并声明指针类型
Go 中用 & 操作符取变量地址,指针类型写作 *T(T 是任意类型)。声明时必须明确指向的具体类型,不能像 C 那样用 void* 混用。
常见错误是把 & 误写成 *,或对常量、字面量取地址(如 &42 或 &"hello"),Go 编译器会直接报错:cannot take the address of …。
- 正确写法:
age := 25 ptr := &age // ptr 类型是 *int
- 错误写法:
ptr := *age // 编译失败:* 用于解引用,不是取地址
- 结构体字段可取地址,但需确保字段本身可寻址(例如不能对 map 中的值直接取地址)
如何解引用指针并安全修改值
用 * 解引用指针才能读写其指向的值。若指针为 nil 时解引用,运行时 panic:invalid memory address or nil pointer dereference。
Go 不支持指针算术(如 ptr++),也不允许将普通整数转为指针(unsafe.Pointer 除外,但属非安全操作)。
立即学习“go语言免费学习笔记(深入)”;
- 安全解引用前建议判空:
if ptr != nil { *ptr = 30 // 修改原变量 age 的值 } - 函数传参时传
*T可在函数内修改原始变量,这是 Go 中实现“输出参数”的常用方式 - 切片、map、channel 本身是引用类型,传参时不需额外加
*;只有需要修改其底层数组头或哈希表指针时才考虑传指针
函数参数中传递指针的典型场景
当函数需要修改调用方的变量,或避免复制大结构体时,应使用指针参数。但不要盲目加 *——小类型(如 int、string)传值开销极小,且更清晰安全。
注意:接收指针参数的函数,调用时必须传变量地址,不能传字面量或只读表达式结果。
- 正确调用:
func updateName(p *string) { *p = "Alice" } name := "Bob" updateName(&name) // ✅ - 错误调用:
updateName(&"Charlie") // ❌ 编译失败
- 结构体方法接收者用指针时,才能修改字段:
func (u *User) SetAge(a int) { u.Age = a }
指针与 nil 的边界行为
所有指针类型初始零值都是 nil,但不同指针类型之间不可互赋(*int 和 *string 不兼容)。判断是否为 nil 是唯一安全的指针比较操作。
容易被忽略的是:接口变量内部存储了动态类型和值,若将一个 nil 指针赋给接口,该接口本身不为 nil(因为类型信息存在),这会导致意外的 nil 判断失效。
- 示例陷阱:
var p *int = nil var i interface{} = p fmt.Println(i == nil) // false!i 不是 nil,它装了一个 *int 类型的 nil 值 - 检查接口内指针是否为
nil,得用类型断言后判断:if v, ok := i.(*int); ok && v == nil { ... } - struct 字段为指针时,JSON 反序列化默认会设为
nil,需手动初始化或用指针字段配合omitempty控制输出










