如何在Golang中使用Protobuf.any?

9

我将在我的Go项目中使用gRPC。以下是代码:

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

但我不确定如何处理细节(interface{})字段。我知道我可以使用任何类型来表示接口,但不确定如何在这里使用它。有人可以帮忙吗?谢谢

5个回答

12

因为protobuf/ptypes已经被弃用,所以值得使用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
}


9

protobuf/ptypes 包含一些工具,可以将任意 proto 消息转换为以下任意类型:


MarshalAny:

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

MarshalAny函数将给定的消息m编组为anypb.Any消息。


UnmarshalAny

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

UnmarshalAny函数将anypb.Any消息中包含的编码值解码为提供的消息m。如果目标消息与Any消息中的类型不匹配或发生解码错误,则返回错误。


在你的例子中,你会使用类似以下的东西:
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)
}

但目前,“d”只是一个“interface{}”,而不是“proto.Message”。这是否意味着我需要先将其制作为Proto消息?如果是,那我该如何操作? - jason135
1
最终,protobuf.Any 必须是一个 proto.Message。你可以直接传递一个,或者进行类型断言。例如:d.(proto.Message) - Marc
1
已弃用:请改为调用 any.UnmarshalTo 方法。 - borud

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)

使用anypb.New API,在您的代码中,将d传递给pbany函数。

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

-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

}


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接