如何将结构转换/转换为 Protobuf?

我正在开发一个个人项目,并且是第一次使用 Go。我使用结构来操作数据并将数据存储在文件中,我使用 proto 作为编码器。


在项目中,我的原型定义看起来像这样


message Data {

    string key = 1;

    string value = 2;

}


message Record {

    int64 size = 1;

    Data data = 2;

}

我的结构看起来像这样


type KVData struct {

    Key       string

    Value     string

}

目前,这就是我创建原始数据的方式


kvData := KVData{Key: "name", Value: "A"}


record := &pb.Record{

        Size: 20,

        Data: &pb.Data{Key: "name", Value: "A"},

}

我正在寻找一种方法来做到这一点:


record := &pb.Record{

        Size: 20,

        Data: &((pb.Data)kvData), // Won't work

}


// or like Python


record := &pb.Record{

        Size: 20,

        Data: &(pb.Data{**kvData}), // Won't work

}


我尝试谷歌搜索,但找不到任何解释如何执行此操作的解决方案。


请注意,我不仅仅是想解决这个特定的情况,我还想知道在结构和原型之间操作的推荐Go方式是什么(仅使用原型?)?


人到中年有点甜
浏览 229回答 3
3回答

鸿蒙传说

你不能,至少在 Go 1.12.7 中不能。Go 的 Protobuf 编译器向消息生成的每个结构添加 3 个额外字段:XXX_NoUnkeyedLiteral         struct{} `json:"-"`XXX_unrecognized             []byte   `json:"-"`XXX_sizecache                int32    `json:"-"`因此,您的struct和生成的字段具有不同的字段并且不相同,因此不可分配。如果两个结构仅在标签上不同,则可以将其转换:type Person struct {    Name    string    Address *struct {        Street string        City   string    }}var data *struct {    Name    string `json:"name"`    Address *struct {        Street string `json:"street"`        City   string `json:"city"`    } `json:"address"`}var person = (*Person)(data)  // ignoring tags, the underlying types are identical您必须struct手动创建一个新实例。

小怪兽爱吃肉

你能得到的最接近的是这样的:pbData := pb.Data(kvData) // convert kvData struct to pb.Data structrecord := &pb.Record{        Size: 20,        Data: &pbData,}注意:您不能像这样组合这两个步骤:record := &pb.Record{    Size: 20,    Data: &(pb.Data(kvData)), // BROKEN: can't get address of a return-value}您可以在这里进行更多实验:https ://play.golang.org/p/2AhWi0Khe4l编辑:如果Go 1.8之前的结构类型不完全相同(相同的标签等),则无法转换它们。更新的 Playground 链接到演示不匹配的标签将与go 1.8或稍后进行转换。

叮当猫咪

您可以使用第三方库 gogofaster 从 .proto 文件生成 go 代码。gogofaster 是一个更快的生成工具,它不包含结构中的额外字段 (XXX_*),从而使转换更简单(因为结构现在将是相同的)。
打开App,查看更多内容
随时随地看视频慕课网APP