微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

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

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

我第一次使用 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 语言一样嵌入它们吗?

解决方法

您可以简单地使用经常重复的字段定义一个新消息,并将其用作其他消息中的字段类型:

message Metadata {
  uint64 id = 1;
  google.protobuf.Timestamp createdAt = 2;
  google.protobuf.Timestamp updatedAt = 3;
}

message League {
  Metadata metadata = 1;
  string name = 2;
  //...
}

在 Go 中,您将 Metadata 字段初始化为普通结构(包选择器将取决于您实际如何从 protobuffers 生成 Go 类型):

func newLeague() *grpcgen.League {
    return &grpcgen.League{
       Metadata: &grpcgen.Metadata{
           Id:        1000,CreatedAt: ptypes.TimestampProto(time.Now()),UpdatedAt: ptypes.TimestampProto(time.Now()),}
       Name: "foo",//...
    }
}

编辑:

您认为这会减慢编码/解码过程吗

我们可以运行以下基准测试:

package foo

import (
    "github.com/golang/protobuf/proto"
    "github.com/golang/protobuf/ptypes"
    "foo/grpcgen"
    "testing"
)

var withmeta = &grpcgen.LeagueWithMeta{
    Metadata: &grpcgen.Metadata{
        Id: 1000,CreatedAt: ptypes.TimestampNow(),UpdatedAt: ptypes.TimestampNow(),},Name: "foo",}

var nometa = &grpcgen.LeagueNoMeta{
    Id: 1000,}

func BenchmarkEncProto(b *testing.B) {
    b.Run("encode with meta",func(b *testing.B) {
        b.ReportAllocs()
        for i := 0; i < b.N; i++ {
            b,_ := proto.Marshal(withmeta)
            if b == nil {
                panic("not marshaled")
            }
        }
    })

    b.Run("encode without meta",_ := proto.Marshal(nometa)
            if b == nil {
                panic("not marshaled")
            }
        }
    })
}
$ go test -bench=. ./proto_benchmark_test.go -benchtime=10s
goos: darwin
goarch: amd64
cpu: Intel(R) Core(TM) i7-7660U CPU @ 2.50GHz
BenchmarkEncProto/encode_with_meta-4            13124650           948.8 ns/op        96 B/op          4 allocs/op
BenchmarkEncProto/encode_without_meta-4         25832161           417.0 ns/op        64 B/op          2 allocs/op
PASS
ok      command-line-arguments  24.629s

Not 将字段包装在 Metadata 消息中具有更好的性能,这并不奇怪。实际上,这不会以明显的方式影响您的程序。

,

您可以使用通用字段创建消息:

message Meta {
  uint64 id=1;
  google.protobuf.Timestamp createdAt = 2;
  google.protobuf.Timestamp updatedAt = 3;
}

message Player {
  Meta meta=1;
  string firstname = 4;
  string lastname = 5;
  //...
}

message Team {
  Meta id = 1;
  string name = 2;
  //...
}
message League {
  Meta meta=1;
  string name = 2;
  //...
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。