如何不对每个原型结构重复相同的字段?

我第一次使用protobuf .proto文件。


我有许多模型具有相同的字段:


message Player {

  uint64 id = 1;

  google.protobuf.Timestamp createdAt = 2;

  google.protobuf.Timestamp updatedAt = 3;

  string firstname = 4;

  string lastname = 5;

  //...

}

message Team {

  uint64 id = 1;

  google.protobuf.Timestamp createdAt = 2;

  google.protobuf.Timestamp updatedAt = 3;

  string name = 4;

  //...

}

message League {

  uint64 id = 1;

  google.protobuf.Timestamp createdAt = 2;

  google.protobuf.Timestamp updatedAt = 3;

  string name = 4;

  //...

}

...和许多其他...


如您所见,我在每个结构中都重复了相同的字段。


在这种情况下,DRY(不要重复自己)的最佳实践是什么?


我正在使用Golang。


我可以像在 Go 语言中一样嵌入它们吗?


慕姐4208626
浏览 72回答 1
1回答

12345678_0001

您只需使用经常重复的字段定义一个新消息,并将其用作其他消息中的字段类型:message Metadata {&nbsp; uint64 id = 1;&nbsp; google.protobuf.Timestamp createdAt = 2;&nbsp; google.protobuf.Timestamp updatedAt = 3;}message League {&nbsp; Metadata metadata = 1;&nbsp; string name = 2;&nbsp; //...}在 Go 中,您将该字段初始化为普通结构(包选择器将取决于您如何从 protobuffers 实际生成 Go 类型):Metadatafunc newLeague() *grpcgen.League {&nbsp; &nbsp; return &grpcgen.League{&nbsp; &nbsp; &nbsp; &nbsp;Metadata: &grpcgen.Metadata{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Id:&nbsp; &nbsp; &nbsp; &nbsp; 1000,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;CreatedAt: ptypes.TimestampProto(time.Now()),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;UpdatedAt: ptypes.TimestampProto(time.Now()),&nbsp; &nbsp; &nbsp; &nbsp;}&nbsp; &nbsp; &nbsp; &nbsp;Name: "foo",&nbsp; &nbsp; &nbsp; &nbsp;//...&nbsp; &nbsp; }}编辑:你认为这会减慢编码/解码过程吗?我们可以运行以下基准测试:package fooimport (&nbsp; &nbsp; "github.com/golang/protobuf/proto"&nbsp; &nbsp; "github.com/golang/protobuf/ptypes"&nbsp; &nbsp; "foo/grpcgen"&nbsp; &nbsp; "testing")var withmeta = &grpcgen.LeagueWithMeta{&nbsp; &nbsp; Metadata: &grpcgen.Metadata{&nbsp; &nbsp; &nbsp; &nbsp; Id: 1000,&nbsp; &nbsp; &nbsp; &nbsp; CreatedAt: ptypes.TimestampNow(),&nbsp; &nbsp; &nbsp; &nbsp; UpdatedAt: ptypes.TimestampNow(),&nbsp; &nbsp; },&nbsp; &nbsp; Name: "foo",}var nometa = &grpcgen.LeagueNoMeta{&nbsp; &nbsp; Id: 1000,&nbsp; &nbsp; CreatedAt: ptypes.TimestampNow(),&nbsp; &nbsp; UpdatedAt: ptypes.TimestampNow(),&nbsp; &nbsp; Name: "foo",}func BenchmarkEncProto(b *testing.B) {&nbsp; &nbsp; b.Run("encode with meta", func(b *testing.B) {&nbsp; &nbsp; &nbsp; &nbsp; b.ReportAllocs()&nbsp; &nbsp; &nbsp; &nbsp; for i := 0; i < b.N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b, _ := proto.Marshal(withmeta)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if b == nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic("not marshaled")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; })&nbsp; &nbsp; b.Run("encode without meta", func(b *testing.B) {&nbsp; &nbsp; &nbsp; &nbsp; b.ReportAllocs()&nbsp; &nbsp; &nbsp; &nbsp; for i := 0; i < b.N; i++ {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; b, _ := proto.Marshal(nometa)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if b == nil {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; panic("not marshaled")&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; })}$ go test -bench=. ./proto_benchmark_test.go -benchtime=10sgoos: darwingoarch: amd64cpu: Intel(R) Core(TM) i7-7660U CPU @ 2.50GHzBenchmarkEncProto/encode_with_meta-4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 13124650&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;948.8 ns/op&nbsp; &nbsp; &nbsp; &nbsp; 96 B/op&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 4 allocs/opBenchmarkEncProto/encode_without_meta-4&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;25832161&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;417.0 ns/op&nbsp; &nbsp; &nbsp; &nbsp; 64 B/op&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 2 allocs/opPASSok&nbsp; &nbsp; &nbsp; command-line-arguments&nbsp; 24.629s不包装消息中的字段具有更好的性能,这并不奇怪。在实践中,这不会以可观的方式影响您的程序。Metadata
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go