Unmarshal Go database query results into gRPC/protobuf structs

gRPC

gRPC is an incredibly powerful alternative to JSON-RPC and all kinds of custom RESTful APIs we invent for microservice communication.

You define message types and service methods in an IDL called Protocol Buffers. These protobuf files are used to generate client and server code for your target language.

Protobuf message types get transpiled to structs in Go. If you use something like sqlx to query a database and return the result over gRPC you would have to add custom tags to your structs to specify which struct fields correspond to which database fields. See the sqlx usage example for more details.

Introducing protoc-go-inject-tag

Since these message structs are automatically generated from protobuf IDL there is no way to add these tags by default. Fortunately there is a great tool which allows us to inject custom Go tags into structs using comments in protobuf files - protoc-go-inject-tag.

Consider the following example from the gRPC homepage with a db tag added as a comment:

message HelloRequest {
  string greeting = 1;
}

message HelloResponse {
  // @inject_tag: db:"hello_reply"
  string reply = 1;
}

service HelloService {
  rpc SayHello(HelloRequest) returns
  (HelloResponse);
}

In the generated Go code you will see this:

Reply string `protobuf:"bytes,1,opt,name=reply" json:"reply,omitempty" db:"hello_reply"`

Now you can use this struct with sqlx:

var res HelloResponse
db.Get(&res, `SELECT hello_reply FROM replies WHERE id = ?`, 123)