Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to use protobuf.any in golang

I'm using grpc in my go project. Below is code:

example.proto:

syntax = "proto3";

message Example {
    string message = 1;
    google.protobuf.Any details = 2;
}

main.go

func logMessage (m string, d interface{}) {
    message := & example.message{
       message: m,
       details: ??
    }    
    log(&message)
}

But I'm not sure how to deal with the details(interface{}) field. I know I can use any type for interface, but not sure how to use it here. Anyone can help? Thanks

like image 332
jason135 Avatar asked Sep 24 '20 23:09

jason135


2 Answers

Since protobuf/ptypes is deprecated, it worth using anypb.UnmarshalTo

import (
    "google.golang.org/protobuf/types/known/anypb"
    "github.com/golang/protobuf/ptypes/any"
)

func Unmarshal(data *any.Any) (*YourMessage, err) {
    var m YourMessage
    err := anypb.UnmarshalTo(data, &m, proto.UnmarshalOptions{})
    return &m,err
}

like image 77
igorushi Avatar answered Sep 18 '22 09:09

igorushi


The protobuf/ptypes package has utilities to convert to/from arbitrary proto messages to any:


MarshalAny:

func MarshalAny(m proto.Message) (*anypb.Any, error)

MarshalAny marshals the given message m into an anypb.Any message.


UnmarshalAny:

func UnmarshalAny(any *anypb.Any, m proto.Message) error

UnmarshalAny unmarshals the encoded value contained in the anypb.Any message into the provided message m. It returns an error if the target message does not match the type in the Any message or if an unmarshal error occurs.


In your example, you would use something along the lines of:

func logMessage (m string, d proto.Message) {
    details, err := ptypes.MarshalAny(d)
    if err != nil {
        panic(err)
    }
    message := & example.message{
        message: m,
        details: details
    }    
    log(&message)
}
like image 24
Marc Avatar answered Sep 19 '22 09:09

Marc