
go语言的json.unmarshal函数仅能反序列化导出(exported)字段,而导出字段要求名称首字母必须大写;小写字母开头的字段因不可导出,会被忽略并保持零值。
go语言的json.unmarshal函数仅能反序列化导出(exported)字段,而导出字段要求名称首字母必须大写;小写字母开头的字段因不可导出,会被忽略并保持零值。
在Go语言中,结构体字段能否被外部包(包括标准库如 encoding/json)访问,完全取决于其可见性(visibility)规则:只有首字母大写的字段才是导出字段(即公开的、可被其他包访问),而首字母小写的字段属于非导出字段(私有),仅限于定义它的包内使用。
json.Unmarshal 作为 encoding/json 包中的函数,运行在当前包之外(即使在同一包中,它也通过反射机制统一处理),因此只能读取和设置导出字段。当 JSON 数据尝试填充一个包含小写字段(如 name string)的结构体时,该字段因不可导出而被跳过,最终保留其类型的零值(例如 ""、0、false 或 nil)。
以下是一个典型对比示例:
将一个或多个视频上传至YouTube。当用户想“上传到YouTube”“发YouTube”“批量上传”“upload to YouTube”“post videos to YouTube”或发布到YouTube时使用此技能。
package main
import (
"encoding/json"
"fmt"
)
type GameOne struct {
Name string `json:"name"` // 首字母大写 → 导出 → 可反序列化
}
type GameTwo struct {
name string `json:"name"` // 首字母小写 → 非导出 → 被忽略
}
func main() {
data := []byte(`{"name":"Chess"}`)
var g1 GameOne
json.Unmarshal(data, &g1)
fmt.Printf("GameOne.Name = %q\n", g1.Name) // 输出: "Chess"
var g2 GameTwo
json.Unmarshal(data, &g2)
fmt.Printf("GameTwo.name = %q\n", g2.name) // 输出: ""(空字符串,零值)
}⚠️ 注意事项:
立即学习“go语言免费学习笔记(深入)”;
- JSON 标签(如
`json:"name"`)仅影响键名映射,不能绕过导出规则; - 即使添加了
json:"name"标签,小写字段仍不会被反序列化; - 若需隐藏字段但又支持 JSON 解析,应使用大写首字母 + 自定义 JSON 标签,并结合
json:"-"显式忽略(如Password stringjson:"-"`); - 同理,
json.Marshal也仅输出导出字段。
总结:这不是 json 包的限制,而是 Go 语言封装与反射机制的设计原则——反射无法访问非导出标识符。因此,在设计需 JSON 序列化的结构体时,务必确保所有目标字段首字母大写,并合理使用 struct tag 控制序列化行为。

















