go中声明指针变量的语法是var p *int,*为类型构造符而非修饰符;p零值为nil,需用&x取地址赋值,不可省略&,也不能用p = x赋值。

Go里声明指针变量的语法是 *T
Go中指针类型本身是独立类型,不是修饰符。声明一个指向int的指针,写法是 var p *int,不是 int* 那种C风格。这里的 * 是类型构造符,和取值操作符 * 同形但语义不同。
常见错误是把声明和初始化混为一谈:只写 var p *int 时,p 的零值是 nil,它不指向任何有效内存;想让它指向某个变量,得用取地址符 & 显式赋值:
var x int = 42 var p *int = &x // 正确:&x 得到 x 的地址
如果漏掉 &,比如写成 p = x,编译器会直接报错:cannot use x (type int) as type *int in assignment。
声明并初始化可以一步完成,但别混淆 new 和 &
有两种常用方式快速获得指针:
-
p := new(int):调用内置函数new,分配零值内存并返回其地址,等价于var v int; p := &v -
p := &x:对已有变量取地址,最常用、最直观
注意 new(T) 只能用于类型字面量(如 int、struct{}),不能用于变量或表达式;而 & 只能用于可寻址的变量(比如不能写 &(x + 1))。
性能上没区别,但语义不同:new 暗示“我要一块新内存”,& 暗示“我要这个变量的地址”。多数场景优先用 &,更清晰。
指针类型变量不能直接比较(除非同为 nil 或同源)
Go允许用 == 比较两个相同类型的指针,但结果只在两种情况下可靠:
- 都为
nil→true - 指向同一个变量(比如
p := &x; q := &x)→true
如果两个指针分别指向内容相同的两个不同变量(比如两个值都是42的 int),p == q 仍是 false。这点和C不同,Go不支持指针算术,也不鼓励通过地址值做逻辑判断。
需要比内容时,应解引用后比较:*p == *q,但要先确保二者非 nil,否则 panic。
声明指针字段的 struct 时,注意零值是 nil 而非空结构体
定义如下的结构体:
type User struct {
Name *string
Age *int
}
当写 u := User{} 时,u.Name 和 u.Age 都是 nil,不是空字符串或0。如果后续直接 *u.Name,会 panic。
这种设计适合可选字段,但容易漏掉空指针检查。常见做法是在初始化时显式赋值,或用工厂函数封装:
func NewUser(name string, age int) User {
return User{
Name: &name,
Age: &age,
}
}
不过要注意:传入的 name 和 age 是参数副本,取地址后生命周期安全;但如果传入的是切片或 map,取地址意义不大——它们本身已是引用类型。
真正容易被忽略的是:指针字段的 JSON 序列化行为。默认情况下,nil 指针字段在 json.Marshal 中会被省略,这常被误认为“字段没传”,其实是设计使然。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











