
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 输出的基础实践。