如果您想在从/到 MongoDB 编组/解组您的值时更改值或进行类型转换,您可以通过实现自定义编组/解组逻辑来实现。
您可以通过实现bson.Getter 和bson.Setter 接口来做到这一点。在这些方法中,您可以对正在编组/取消编组的值做任何您想做的事情。
最简单的方法是使用附加字段扩展您的 clientConfigData 类型,该字段的类型为 time.Time,您需要的值:
type clientConfigData struct {
SMTPAssoc int `bson:"smtp_assoc"`
PlanType string `bson:"plan_type"`
EndDateStr string `bson:"end_date"`
EndDate time.Time `bson:"-"`
}
它有标签值bson:"-",因为我们不希望它出现在MongoDB中。
现在自定义编组/解组逻辑:
const endDateLayout = "2006-01-02 15:04:05" // Use your layout here
func (c *clientConfigData) SetBSON(raw bson.Raw) (err error) {
type my clientConfigData
if err = raw.Unmarshal((*my)(c)); err != nil {
return
}
c.EndDate, err = time.Parse(endDateLayout, c.EndDateStr)
return
}
func (c *clientConfigData) GetBSON() (interface{}, error) {
c.EndDateStr = c.EndDate.Format(endDateLayout)
type my *clientConfigData
return my(c), nil
}
这里发生的情况是SetBSON() 负责使用来自 MongoDB 的原始值“填充”您的结构值,而GetBSON() 负责提供您想要保存(封送)的值。
加载时:SetBSON() 首先按原样解组值,然后从来自 DB (EndDateStr )。
保存时:GetBSON()首先从EndDate字段填充EndDateStr字段(被保存的那个),然后简单地返回,表示可以保存。
需要注意的一点:SetBSON() 和 GetBSON() 在其中创建一个新的 my 类型。这样做的原因是为了避免堆栈溢出。简单地返回一个clientConfigData 类型的值是不好的,因为我们实现了bson.Getter 和bson.Setter,所以SetBSON() 和GetBSON() 会被无休止地调用。新的my 类型没有这些方法,因此不会发生无休止的“递归”(type 关键字会创建一个新类型,并且它不会“继承”底层类型的方法)。
另见相关/类似问题:Set default date when inserting document with time.Time field