从bson结构转换protoc生成的结构的最佳方法是什么?

Ewa*_*ine 7 go mongodb mgo grpc

我在Golang中编写了一个RESTful API,它也有一个gRPC api.API连接到MongoDB数据库,并使用结构来映射实体.我也有一个.proto定义,它与我用于MongoDB的结构类似.

我只是想知道是否有一种方法可以共享或重新使用.proto定义的MongoDB调用代码.我注意到strucs protoc生成的每个字段都有json标签,但显然没有bson标签等.

我有类似......

// Menu -
type Menu struct {
    ID          bson.ObjectId      `json:"id" bson"_id"`
    Name        string             `json:"name" bson:"name"`
    Description string             `json:"description" bson:"description"`
    Mixers      []mixers.Mixer     `json:"mixers" bson:"mixers"`
    Sections    []sections.Section `json:"sections" bson:"sections"`
}
Run Code Online (Sandbox Code Playgroud)

但后来我也有protoc生成的代码......

type Menu struct {
    Id          string     `protobuf:"bytes,1,opt,name=id" json:"id,omitempty"`
    Name        string     `protobuf:"bytes,2,opt,name=name" json:"name,omitempty"`
    Description string     `protobuf:"bytes,3,opt,name=description" json:"description,omitempty"`
    Mixers      []*Mixer   `protobuf:"bytes,4,rep,name=mixers" json:"mixers,omitempty"`
    Sections    []*Section `protobuf:"bytes,5,rep,name=sections" json:"sections,omitempty"`
}
Run Code Online (Sandbox Code Playgroud)

目前我不得不根据我正在做的事情在两个结构之间进行转换.这很乏味,而且我可能会受到相当大的性能影响.那么是否有更好的方法在两者之间进行转换,或者为两个任务重新使用其中一个?

Liy*_*ang 2

遇到同样的问题后,有几种方法可以解决它。它们分为两种通用方法:

  1. 使用相同的数据类型
  2. 使用两种不同的结构类型并在它们之间进行映射

如果您想使用相同的数据类型,则必须修改代码生成

您可以使用像gogoprotobuf这样的东西,它有一个扩展来添加标签。这应该会给bson你的结构中的标签。

您还可以使用正则表达式或更复杂的涉及 go 抽象语法树的方式对生成的文件进行后处理。

如果您选择在它们之间映射:

  1. 使用reflection。您可以编写一个包含两个结构的包,并尝试从一个结构中获取值并将其应用到另一个结构中。您必须处理边缘情况(轻微的命名差异、哪些类型是等效的等),但如果出现边缘情况,您将可以更好地控制它们。

  2. 使用 JSON 作为中介。只要生成的 json 标签匹配,这将是一个快速的编码练习,并且如果代码中没有紧密循环,则序列化和反序列化的性能影响可能是可以接受的。

  3. 手写或代码生成映射函数。根据您拥有的结构数量,您可以编写一堆在两者之间进行转换的函数。

在我的工作场所,我们最终做了其中的一些工作:分叉协议生成器来执行一些自定义标记,用于在任意结构之间映射的基于反射的结构覆盖包,以及一些对性能更敏感或自动化程度较低的手写结构映射。