ProtoMessage方法的目的是什么?

时间:2017-12-17 16:48:50

标签: go protocol-buffers

当我从协议缓冲区文件生成go代码时,我注意到每个生成的结构都实现了Message接口,https://github.com/golang/protobuf/blob/master/proto/lib.go#L277

有关生成的代码的示例,请参阅https://github.com/google/go-genproto/blob/master/googleapis/rpc/status/status.pb.go#L97

显然,Message接口,String()和Reset()上的其他方法有一个明显的目的,具体的实现示例清楚地说明了这一点。但是,我不了解ProtoMessage()方法的目的。该方法不带参数,也不返回参数,为什么会出现?

1 个答案:

答案 0 :(得分:2)

引自官方文件:Protocol Buffers: Go Generated Code:

  

给出一个简单的消息声明:

message Foo {}
     

协议缓冲区编译器生成一个名为Foo的结构。 *Foo实现Message接口。有关详细信息,请参阅内联注释。

type Foo struct {
}

// Reset sets the proto's state to default values.
func (m *Foo) Reset()         { *m = Foo{} }

// String returns a string representation of the proto.
func (m *Foo) String() string { return proto.CompactTextString(m) }

// ProtoMessage acts as a tag to make sure no one accidentally implements the
// proto.Message interface.
func (*Foo) ProtoMessage()    {}
     

请注意,所有这些成员始终存在; optimize_for选项不会影响Go代码生成器的输出。

这是Go官方FAQ: How can I guarantee my type satisfies an interface?

中描述的(类似)技术
  

如果您希望接口的用户明确声明他们实现它,您可以向接口的方法集添加一个带有描述性名称的方法。例如:

type Fooer interface {
    Foo()
    ImplementsFooer()
}
     

然后,类型必须将ImplementsFooer方法实现为Fooer,明确记录事实并在godoc的输出中公布。

type Bar struct{}
func (b Bar) ImplementsFooer() {}
func (b Bar) Foo() {}
     

大多数代码都没有使用这些约束,因为它们限制了界面理念的效用。但有时,他们需要解决类似界面之间的歧义。

因此ProtoMessage()方法基本上有两个目的:

  • 主要目的是在生成的代码中记录:确保您不传递protobuf序列化/反序列化的值,否则(没有此方法)将实现proto.Message接口但不是a"真实" protobuf消息值:
      

    ProtoMessage充当标记,以确保没有人意外地实现proto.Message接口。

  • 它还记录了类型是(实现)Message的事实。这可能没有真正的价值,因为代码是生成的,你不应该费心,但代码分析器和Go IDE可以很好地利用它;它也出现在生成的文档中。