
go 的 `json.marshal` 只能序列化导出(首字母大写)的结构体字段;未导出字段(小写开头)会被忽略,导致输出空对象 `{}`。
在 Go 语言中,JSON 序列化依赖于反射机制,而反射仅能访问导出(exported)字段——即字段名以大写字母开头的成员。你代码中的 Configitem 和 GuiConfig 所有字段均以小写字母开头(如 local_address、configs),因此 json.Marshal 无法读取它们的值,最终返回空 JSON 对象 {}。
✅ 正确做法是将所有需序列化的字段改为导出字段,并推荐添加 json 标签以控制键名和可选行为:
type Configitem struct {
LocalAddress string `json:"local_address"`
LocalPort int `json:"local_port"`
Method string `json:"method"`
Password string `json:"password"`
Server string `json:"server"`
ServerPort string `json:"server_port"`
Timeout int `json:"timeout"`
}
type GuiConfig struct {
Configs []*Configitem `json:"configs"`
Index int `json:"index"`
}修改后,原 main 函数无需改动,即可正确输出:
{"configs":[{"local_address":"eouoeu","local_port":111,"method":"eoeoue","password":"ouoeu","server":"oeuoeu","server_port":"qoeueo","timeout":3333}],"index":1}⚠️ 注意事项:
- 字段名首字母必须大写(如 LocalAddress),否则仍不可导出;
- json 标签中的键名可保持小写(如 "local_address"),兼顾 Go 命名规范与 JSON 兼容性;
- 若因封装需求必须保留字段私有性,可手动实现 json.Marshaler 接口,但会增加维护成本,一般不推荐;
- 切勿依赖 unsafe 或反射绕过导出规则——这违背 Go 的设计哲学,且易引发兼容性问题。
总结:Go 的序列化安全模型建立在“导出即可见”原则之上。让结构体支持 JSON,第一步永远是——检查并修正字段的导出状态。










