ProtoMessage方法的目的是什么?

问题描述 投票:3回答:1

当我从协议缓冲区文件生成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()方法的目的。该方法不带参数,也不返回任何参数,为什么会出现?

go protocol-buffers
1个回答
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接口但不是“真正的”protobuf消息值: ProtoMessage充当标记,以确保没有人意外地实现proto.Message接口。
  • 它还记录了类型是(实现)Message的事实。这可能没有真正的价值,因为代码是生成的,你不应该费心,但代码分析器和Go IDE可以很好地利用它;它也出现在生成的文档中。
© www.soinside.com 2019 - 2024. All rights reserved.