ProtoMessage 方法的目的是啥?

Posted

技术标签:

【中文标题】ProtoMessage 方法的目的是啥?【英文标题】:What's the purpose of ProtoMessage method?ProtoMessage 方法的目的是什么? 【发布时间】:2017-12-17 16:48:49 【问题描述】:

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

【问题讨论】:

猜测(因此为什么这是评论,而不是答案),我会说这是为了确保您不会意外实现 Message 接口。只有StringReset 方法,太多的东西会匹配。例如:如果不需要ProtoMessage()bytes.Buffer 将实现接口。 【参考方案1】:

引用官方文档:Protocol Buffers: Go Generated Code:

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

message Foo 

protocol buffer 编译器生成一个名为Foo 的结构。 *Foo 实现了 Message 接口。有关详细信息,请参阅内联 cmets。

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()方法基本上有2个用途:

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

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

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

【讨论】:

以上是关于ProtoMessage 方法的目的是啥?的主要内容,如果未能解决你的问题,请参考以下文章

类方法的目的是啥?

AuthorizationServerSecurityConfigurer 中的领域方法的目的是啥?

EAAccessoryDe​​legate 中的 –accessoryDidDisconnect: 方法的目的是啥?

“!”的目的是啥?和 ”?”在方法名称的末尾?

Enum Singleton中静态getInstance方法的目的是啥?

将方法参数声明为 final 的目的是啥? [复制]