
go 的 `json.marshal` 默认仅导出首字母大写的字段;若结构体字段为小写(未导出),序列化结果将为空对象,需通过标签和导出字段确保数据正确输出。
在 Go 中,JSON 编码(marshalling)遵循严格的可见性规则:只有导出字段(即首字母大写的字段)才能被 encoding/json 包访问并序列化。你定义的 SpanInfo 结构体中所有字段均为小写(如 imsi、network),属于未导出字段,因此 json.Marshal 无法读取其值,最终生成 [{},{},{},{}] 这样的空对象数组。
要解决此问题,需两步改造:
- 将字段名改为首字母大写,使其可导出;
- 配合 json 标签(tag)指定序列化后的键名,保持 JSON 字段命名风格(如 snake_case)不变。
修正后的结构体定义如下:
type SpanInfo struct {
IMSI string `json:"imsi"`
Network string `json:"network"`
NetworkStatus string `json:"network_status"`
SignalQuality int `json:"signal_quality"`
Slot int `json:"slot"`
State string `json:"state"`
}
type GatewayInfo []SpanInfo此时,即使 GatewayInfo 是类型别名([]SpanInfo),只要其元素类型 SpanInfo 的字段已正确导出并标注,json.Marshal 即可完整序列化整个切片:
func getGatewayInfo(spans []SpanInfo) GatewayInfo {
return GatewayInfo(spans)
}
// 使用示例
gatewayInfo := getGatewayInfo([]SpanInfo{
{IMSI: "652020105829193", Network: "20801", NetworkStatus: "Registered (Roaming)", SignalQuality: 17, Slot: 2, State: "active"},
{IMSI: "652020105829194", Network: "20801", NetworkStatus: "Registered (Roaming)", SignalQuality: 16, Slot: 3, State: "standby"},
})
data, err := json.Marshal(gatewayInfo)
if err != nil {
log.Fatal(err)
}
log.Printf("JSON output: %s", data)
// 输出示例:
// [{"imsi":"652020105829193","network":"20801","network_status":"Registered (Roaming)","signal_quality":17,"slot":2,"state":"active"}, ...]⚠️ 注意事项:
- 若字段无需出现在 JSON 中,可添加 json:"-" 标签忽略;
- 若希望零值字段(如空字符串、0)不输出,可追加 ,omitempty(例如 json:"imsi,omitempty");
- 切片本身无需额外导出——GatewayInfo 是类型别名而非结构体,其序列化行为完全取决于 SpanInfo 字段的导出状态与标签配置。
总结:Go 的 JSON 序列化是“导出即可见”,小写字段等于对 encoding/json 不可见。务必统一使用大写首字母 + json 标签,这是实现可控、可读、符合 API 规范的 JSON 输出的基础实践。










