从Go访问MongoDB

从Go访问MongoDB,mongodb,go,mgo,Mongodb,Go,Mgo,我使用Go访问MongoDB,如下所示: var configRes *clientConfigData err := clientDB. C(clientConfigCollection). Find(bson.M{}). One(&configRes) if err != nil { return nil, errors.Wrap(err, "finding config collection") } 在哪里 type clientConfigDat

我使用Go访问MongoDB,如下所示:

var configRes *clientConfigData
err := clientDB.
    C(clientConfigCollection).
    Find(bson.M{}).
    One(&configRes)
if err != nil {
    return nil, errors.Wrap(err, "finding config collection")
}
在哪里

type clientConfigData struct {
    SMTPAssoc      int       `bson:"smtp_assoc"`
    PlanType       string    `bson:"plan_type"`
    EndDate        string    `bson:"end_date"`
}

现在,由于MongoDB中的
EndDate
存储为
string
,因此我将
EndDate
声明为
string
。但是我需要在
clientConfigData

中以Go
Time
的形式访问此日期。如果您想在将值从MongoDB封送/解封时更改值或进行类型转换,可以通过实现自定义封送/解封逻辑来实现

您可以通过实现和接口来实现这一点。在这些方法中,您可以对封送/取消封送的值执行任何操作

最简单的方法是使用附加字段扩展
clientConfigData
类型,该字段的类型为您需要的值:

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()
首先按原样解组值,然后从数据库(
EndDateStr
)的
字符串中正确设置
EndDate
字段(类型为
time.time

保存时:
GetBSON()
首先从
EndDate
字段填充
EndDateStr
字段(保存的字段),然后返回,表示可以保存

需要注意的一点是:
SetBSON()
GetBSON()
在它们内部创建一个新的
my
类型。这样做的原因是为了避免堆栈溢出。简单地返回类型为
clientConfigData
的值是不好的,因为我们实现了
bson.Getter
bson.Setter
,所以
SetBSON()
GetBSON()
将被无休止地调用。新的
my
类型没有这些方法,因此不会发生无休止的“递归”(关键字
type
创建一个新类型,并且不会“继承”基础类型的方法)


另请参见相关/类似的问题:

因此,如果我们没有实现
bson.Getter
bson.Setter
,我们可以简单地返回
clienConfigData
,对吗?但在这种情况下,我们最好不要。这是正确的吗?你的问题没有真正意义,因为添加
GetBSON()
SetBSON()
实现了
Getter
Setter
Getter
Setter
是定义
GetBSON()
SetBSON()
的接口)。如果你不添加这些方法,就没有什么可以返回的了。非常感谢@icza@icza我只有一个问题,如何对从
SetBSON
@SyedQasimRizvi返回的错误进行错误处理您没有处理它,因为您不是调用
SetBSON()
的人。当从MongoDB加载值时,
mgo
包检查值是否实现了
Setter
,如果实现了,则调用其
SetBSON()
进行解组。需要处理由它返回的
错误的是
mgo
包,它可能被包装、记录或由您调用的外部函数返回(例如
Find().All()
Find().One()
)。