Go操作MongoDB如何实现空结构体字段自动忽略不入库
问题原因
Go MongoDB 官方驱动对omitempty标签的默认判定逻辑中,非指针类型的结构体零值不会被识别为空值,因此你显式赋值的model.Status{}、model.Location{}这类空值结构体会被正常序列化写入库中,不会被省略。
解决方案
以下两种方案都可以实现空结构体自动省略的效果,按需选择即可:
方案1:将嵌套结构体字段改为指针类型(推荐)
这是成本最低、最通用的实现方式,只需要把WorkContract中所有嵌套结构体字段从值类型改为指针类型,修改后的结构体定义示例:
type WorkContract struct { ID primitive.ObjectID `bson:"_id,omitempty"` Code string `bson:"code,omitempty"` Title string `bson:"title,omitempty"` Description string `bson:"description,omitempty"` Profile Profile `bson:"profile,omitempty"` Expertise Expertise `bson:"expertise,omitempty"` Status *Status `bson:"status,omitempty"` Location *Location `bson:"location,omitempty"` BusinessUnit *BusinessUnit `bson:"business_unit,omitempty"` Customer *Customer `bson:"customer,omitempty"` Offer *Offer `bson:"offer,omitempty"` Skills []Skill `bson:"skills,omitempty"` DateStart time.Time `bson:"date_start,omitempty"` DateEnd time.Time `bson:"date_end,omitempty"` }
对应构造对象时,不需要赋值的空字段直接留空即可,指针类型的零值是nil,驱动会自动识别为零值并配合omitempty省略,不需要显式赋值空结构体:
func generateWorkContract() *model.WorkContract { return &model.WorkContract{ Code: workcontract.Code, Title: workcontract.Title, Description: workcontract.Description, Profile: *mapper.profilesMapper.MapToModel(&workcontract.Profile), Expertise: *mapper.expertisesMapper.MapToModel(&workcontract.Expertise), // Status、Location、BusinessUnit等空字段无需显式赋值,默认即为nil Skills: nil, DateStart: workcontract.DateStart, DateEnd: workcontract.DateEnd, } }
修改后重新写入数据,空的嵌套结构体字段就不会被存入MongoDB了。
方案2:为嵌套结构体实现IsZero接口
如果你不想修改原有结构体的字段类型,可以给每个嵌套结构体实现驱动内置支持的IsZero() bool方法,自定义空值判定逻辑。以Status结构体为例:
type Status struct { Code string `bson:"code,omitempty"` Description string `bson:"description,omitempty"` Enabled bool `bson:"enabled,omitempty"` } // IsZero 自定义Status结构体的空值判定规则 func (s Status) IsZero() bool { return s.Code == "" && s.Description == "" && !s.Enabled }
按照相同逻辑给Location、BusinessUnit、Customer、Offer所有嵌套结构体都实现IsZero方法后,驱动序列化时会自动调用该方法判断字段是否为空,返回true时就会配合omitempty标签自动省略该字段。
注意:该方案需要手动给所有嵌套结构体实现空值判定逻辑,后续结构体新增/删除字段时,还要同步修改
IsZero方法的判断规则,维护成本高于指针方案。
内容的提问来源于stack exchange,提问作者Jordi
相关产品推荐
相关产品推荐

