
Go 的 string 类型无法直接表示 JSON 中的 null,必须使用指向字符串的指针(*string)并设为 nil,才能在序列化时生成真正的 null;数组中需混合 *string 元素,部分为 nil,部分指向有效字符串。
go 的 `string` 类型无法直接表示 json 中的 `null`,必须使用指向字符串的指针(`*string`)并设为 `nil`,才能在序列化时生成真正的 `null`;数组中需混合 `*string` 元素,部分为 `nil`,部分指向有效字符串。
在 Go 中,原生类型(如 string、int、bool)均为值类型,其零值(如 ""、0、false)在 JSON 序列化时永远不会变成 null——json.Marshal 仅将 Go 的 nil 指针、nil slice、nil map 或 nil interface 映射为 JSON 的 null。
因此,若希望 JSON 数组中某个元素为 null(例如 ["CEO", "CFO", null, "CMO"]),对应 Go 结构体字段必须声明为 []*string,而非 []string。每个数组项可独立为 *string:指向真实字符串的地址,或显式设为 nil。
✅ 正确实现方式
type JobTitles struct {
Titles []*string `json:"titles"`
}
func main() {
// 定义非空字符串变量(需取地址)
ceo := "CEO"
cfo := "CFO"
cmo := "CMO"
// 构造 []*string:其中第三个元素为 nil → JSON 中即为 null
chiefTitles := []*string{&ceo, &cfo, nil, &cmo}
job := JobTitles{Titles: chiefTitles}
data, err := json.Marshal(job)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
// 输出: {"titles":["CEO","CFO",null,"CMO"]}
}⚠️ 注意事项
- 不能直接写 &"CEO":字符串字面量是不可寻址的,编译会报错 cannot take the address of "CEO"。必须先声明变量再取地址。
-
避免意外 panic:解码含 null 的 JSON 到 []*string 是安全的,但若反向尝试对 nil 指针解引用(如 *s),会导致 panic。建议访问前判空:
for i, s := range job.Titles { if s != nil { fmt.Printf("Title %d: %s\n", i, *s) } else { fmt.Printf("Title %d: <null>\n", i) } } - 替代方案(更简洁):若业务逻辑允许,可定义自定义类型封装可空语义,或使用第三方库(如 github.com/guregu/null),但对纯 JSON 场景,[]*string 是最轻量、标准且无依赖的解法。
? 总结
Go 中实现 JSON 数组内嵌 null 的核心原则是:用指针承载可空性,用 nil 表达缺失。结构体字段应为 []*string,初始化时对需为 null 的位置赋值 nil,其余位置赋值 &someStringVar。该模式同样适用于 *int、*bool 等其他基础类型,是 Go 与 JSON 互操作中处理“可空字段”的通用范式。


















