Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cast/convert a Struct to Protobuf?

I am working on a personal project & using Go for the first time. I am using structs for operating on the data and for storing the data in a file, I am using proto as the encoder.

In the project, my proto definition looks something like this

message Data {
    string key = 1;
    string value = 2;
}

message Record {
    int64 size = 1;
    Data data = 2;
}

and my struct looks like this

type KVData struct {
    Key       string
    Value     string
}

Currently, this is how I am creating proto data

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

record := &pb.Record{
        Size: 20,
        Data: &pb.Data{Key: "name", Value: "A"},
}

What I am looking for is a way to do this:

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
}

I tried googling but couldn't find any solution explaining how to do this.

Note, I am not just trying to solve this specific case, I also want to know what's the recommended Go way to operate between structs and proto(use only proto?)?

like image 212
Amit Tripathi Avatar asked Oct 28 '25 03:10

Amit Tripathi


1 Answers

You cannot, at least not in Go 1.12.7.

Go's Protobuf compiler adds 3 extra fields to each struct generated from a message:

XXX_NoUnkeyedLiteral         struct{} `json:"-"`
XXX_unrecognized             []byte   `json:"-"`
XXX_sizecache                int32    `json:"-"`

Therefore your struct and generated one have different fields and are not identical as per, therefore not assignable.

If two structs differ only in the tags, it is possible to convert it:

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

You have to create a new struct instance manually.

like image 156
Paweł Szczur Avatar answered Oct 30 '25 08:10

Paweł Szczur