bson 方案上的虚拟 属性

Virtuals property on bson scheme

我总是在我的节点项目中使用 mongoose 对文档使用 virtuals properties,并且想在我的 golang 项目中使用相同的机制。我找不到实现类似功能的最佳方法。

我有一些结构,从我的数据库中检索并希望根据我的服务器配置(如 IP 地址等)添加字段。我想避免每次获取此集合的文档时都调用相同的函数。

最简单的方法是简单地向结构添加一个方法来计算您想要的值,并在需要时调用该方法。

例如:

type Person struct {
    FirstName string `bson:"firstName"`
    LastName  string `bson:"lastName"`
}

func (p *Person) Name() string {
    return p.FirstName + " " + p.LastName
}

func main() {
    p := &Person{FirstName: "Bob", LastName: "Archer"}
    fmt.Println(p.Name())
}

这样做的好处是 Name() 将始终 return "correct" 姓名,即使您在检索文档后修改了名字或姓氏也是如此。

如果你想避免总是计算结果,你可以将它存储在一个字段中,例如:

type Person struct {
    FirstName string `bson:"firstName"`
    LastName  string `bson:"lastName"`
    name      string
}

func (p *Person) Name() string {
    if p.name == "" {
        p.name = p.FirstName + " " + p.LastName
    }
    return p.name
}

请注意,当保存值 Person 时,name 字段不会被保留,因为它没有被导出。

如果你想自动执行此操作(例如,你希望在从 MongoDB 获取文档时自动计算 name),你可以通过实现 bson.Setter界面。自定义解组逻辑没什么特别的,只是在执行默认编组逻辑后计算和设置 name 字段。

例如:

type Person struct {
    FirstName string `bson:"firstName"`
    LastName  string `bson:"lastName"`
    name      string
}

func (p *Person) SetBSON(raw bson.Raw) (err error) {
    type my Person
    if err = raw.Unmarshal((*my)(p)); err != nil {
        return
    }
    p.name = p.FirstName + " " + p.LastName
    return nil
}

如果您希望导出 name 字段,例如Name,那么你可以使用 - bson 标签值来排除该字段保存到 MongoDB,例如:

type Person struct {
    FirstName string `bson:"firstName"`
    LastName  string `bson:"lastName"`
    Name      string `bson:"-"`
}