9

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

5 Answers 5

14

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
}

Sign up to request clarification or add additional context in comments.

Comments

11

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)
}

3 Comments

but currently, d is just an interface{} instead of proto.Message. Is that mean I need to make it a proto message first? If yes, how can I do that?
Ultimately, protobuf.Any has to be a proto.Message. You can either pass one directly, or do a type assertion. eg: d.(proto.Message)
Deprecated: Call the any.UnmarshalTo method instead.
3
func pbany(v interface{}) (*anypb.Any, error) {
pv, ok := v.(proto.Message)
if !ok {
    return &anypb.Any{}, fmt.Errorf("%v is not proto.Message", pv)
}
return anypb.New(pv)

use anypb.New api, In your code, pass d to pbany function

Comments

-1
func interfaceToAny(v interface{}) (*anypb.Any, error) {
    bytes, err := json.Marshal(v)
    if err != nil {
        println("error json.Marshal interfaceToAny")
        return nil, err
    }
    m := api.Bytes{B: bytes}
    return anypb.New(&m)
}

message Bytes {
  bytes b = 1;
}

Comments

-1
func ConvertInterfaceToAny(v interface{}) (*any.Any, error) {
 anyValue := &any.Any{}
 bytes, _ := json.Marshal(v)
 bytesValue := &wrappers.BytesValue{
    Value: bytes,
 }
 err := anypb.MarshalFrom(anyValue, bytesValue, proto.MarshalOptions{})
 return anyValue, err

}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.