Google AI提示工程指南解读:把提示词变成可维护的工程产物
2026/10/17 18:21:16
Go的encoding/json包是API开发中使用最频繁的标准库之一。但它的反直觉行为——omitempty对零值的处理、time.Time的默认格式、interface{}反序列化的类型推断——常常成为线上Bug的温床。本文从实战出发,梳理JSON序列化的高阶用法和避坑大全。
typeUserstruct{// 1. 基本用法Namestring`json:"name"`// 2. omitempty:零值时忽略Emailstring`json:"email,omitempty"`// 3. string:数值序列化为字符串Ageint`json:"age,string"`// 4. -:忽略该字段Passwordstring`json:"-"`// 5. 嵌套/扁平化Inner Inner`json:",inline"`}typeOrderstruct{IDint`json:"id,omitempty"`// 0会被省略!Amountfloat64`json:"amount,omitempty"`// 0.0会被省略!Statusstring`json:"status,omitempty"`// ""会被省略!Paidbool`json:"paid,omitempty"`// false会被省略!Time time.Time`json:"time,omitempty"`// 零值时间会被省略!}order:=Order{}json.Marshal(order)// {} ——所有字段都被忽略了!解决方案——使用指针类型:
typeOrderstruct{ID*int`json:"id,omitempty"`// nil时省略Amount*float64`json:"amount,omitempty"`// nil时省略Paid*bool`json:"paid,omitempty"`// nil时省略}typeStatusintconst(StatusPending Status=iotaStatusActive StatusInactive)varstatusToString=map[Status]string{StatusPending:"pending",StatusActive:"active",StatusInactive:"inactive",}varstringToStatus=map[string]Status{"pending":StatusPending,"active":StatusActive,"inactive":StatusInactive,}func(s Status)MarshalJSON()([]byte,error){returnjson.Marshal(statusToString[s])}func(s*Status)UnmarshalJSON(data[]byte)error{varstrstringiferr:=json.Unmarshal(data,&str);err!=nil{returnerr}val,ok:=stringToStatus[str]if!ok{returnfmt.Errorf("未知状态: %s",str)}*s=valreturnnil}typeCustomTimestruct{time.Time}constcustomFormat="2006-01-02 15:04:05"func(ct CustomTime)MarshalJSON()([]byte,error){returnjson.Marshal(ct.Format(customFormat))}func(ct*CustomTime)UnmarshalJSON(data[]byte)error{varsstringiferr:=json.Unmarshal(data,&s);err!=nil{returnerr}t,err:=time.Parse(customFormat,s)iferr!=nil{returnerr}ct.Time=treturnnil}// 对于大量数据,使用Encoder流式写入varbuf bytes.Buffer encoder:=json.NewEncoder(&buf)for_,item:=rangeitems{encoder.Encode(item)// 逐条写入}// 而json.Marshal需要一次性分配所有内存data,_:=json.Marshal(items)typeEventstruct{Typestring`json:"type"`Payload json.RawMessage`json:"payload"`// 延迟解析}funchandleEvent(data[]byte)error{varevent Eventiferr:=json.Unmarshal(data,&event);err!=nil{returnerr}switchevent.Type{case"user_created":varuser User json.Unmarshal(event.Payload,&user)case"order_placed":varorder Order json.Unmarshal(event.Payload,&order)}returnnil}varencoderPool=sync.Pool{New:func()interface{}{returnjson.NewEncoder(nil)},}funcencode(vinterface{})([]byte,error){varbuf bytes.Buffer enc:=json.NewEncoder(&buf)enc.Encode(v)returnbuf.Bytes(),nil}// 统一API响应结构typeAPIResponsestruct{Codeint`json:"code"`Messagestring`json:"message"`Datainterface{}`json:"data,omitempty"`}// null vs 空数组的处理funcSafeSlice[T any](slice[]T)interface{}{ifslice==nil{return[]T{}// 返回空数组而非null}returnslice}func(r APIResponse)WithData(datainterface{})APIResponse{// 自动处理nil切片ifv:=reflect.ValueOf(data);v.Kind()==reflect.Slice&&v.IsNil(){data=reflect.MakeSlice(v.Type(),0,0).Interface()}returnAPIResponse{Code:r.Code,Message:r.Message,Data:data}}