结构体字段为*string时不能直接赋字符串字面量,需用临时变量取址或工厂函数(如StringPtr);嵌套指针字段须逐层显式取址;new(T)仅零值初始化,&T{}支持字段赋值;JSON反序列化中缺失字段保持nil。

结构体字段是 *string 时,不能直接写字符串字面量
Go 不允许把 "hello" 这种字符串字面量直接赋给 *string 类型字段,因为字面量没有地址,无法取址。常见错误是这么写:
type User struct {
Name *string
}
u := User{Name: "alice"} // ❌ compile error: cannot use "alice" (type string) as type *string
正确做法是先声明一个变量再取地址,或用辅助函数封装:
- 最常用:用临时变量 + 取址,例如
name := "alice"; u := User{Name: &name} - 更简洁:用匿名变量取址,
u := User{Name: &[]string{"alice"}[0]}(不推荐,难读) - 工程中建议封装成工厂函数,比如
func StringPtr(s string) *string { return &s },然后写User{Name: StringPtr("alice")}
嵌套结构体含指针字段时,Struct 字面量必须逐层初始化
如果结构体 A 包含字段 B,而 B 是另一个结构体指针(如 *Address),你不能跳过 B 的初始化直接写 Address: {City: "Beijing"} —— Go 会报错说类型不匹配。
典型错误现象:cannot use Address literal (type Address) as type *Address
立即学习“go语言免费学习笔记(深入)”;
- 必须显式取址:
&Address{City: "Beijing"} - 如果 Address 字段本身也含指针(比如
*string的Street),那得继续套一层,比如&Address{Street: StringPtr("Wangfujing")} - 嵌套越深,
&和{}的层级越容易漏配,建议拆成多行、对齐缩进
使用 new() 或 &T{} 初始化指针字段的差异
new(T) 返回 *T,但只做零值初始化;&T{} 也是返回 *T,但支持字段级赋值。两者语义不同,不能混用。
-
u := new(User)→u.Name是nil,不是空字符串指针 -
u := &User{Name: StringPtr("bob")}→u.Name指向有效字符串 - 如果字段是
*int,new(User)后直接解引用会 panic,而&User{Age: new(int)}或&User{Age: IntPtr(25)}才安全 - 性能上无差别,但可读性上
&T{...}更明确意图
JSON 反序列化时 nil 指针字段的坑
用 json.Unmarshal 解析 JSON 到含指针字段的 struct 时,未出现的字段保持 nil,这常被误认为“没解析进去”。但其实这是设计行为,不是 bug。
- 示例:JSON
{"name":"carol"}解到struct{ Name *string; Age *int }→Age是nil,不是 0 - 若想让缺失字段也初始化为零值,得自己实现
UnmarshalJSON方法,或改用值类型字段(如string而非*string) - 前端传空字符串
"age": ""给*int字段会失败(类型不匹配),而*string能接住,这是选择指针的常见理由










