Golang Go语言中 proto3 过滤零值

go proto3 生成的文件,微服务接口会过滤掉零值字段,这个有什么好的解决方式吗?

比如我定义了 name age 两个字段,如果 age 是 0 ,name 返回的时候只有 name 字段,这样不太友好。


Golang Go语言中 proto3 过滤零值
16 回复

ls *.pb.go | xargs -n1 -IX bash -c ‘sed s/,omitempty// X > X.tmp && mv X{.tmp,}’

更多关于Golang Go语言中 proto3 过滤零值的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


或者:

import "google.golang.org/protobuf/encoding/protojson"

m := protojson.MarshalOptions{EmitUnpopulated: true}
resp, err := m.Marshal(w)

0 是作为默认值的,可以减少序列化以后的体积大小,当你反序列化以后,创建出来的数据结构里面的 age 字段在没有设置的时候,也是 0 值,所以从结果上来看是没有什么影响的。

protocol buffer 其实表现力很弱, 自己要额外做很多工作才能用舒服了

我这边用 api 请求 rpc server 出来的时候零值的字段是不存在的,我在 server 端打印的时候就发现零值字段没有,是我哪里写的不对吗

第一个我试过不行, 我再试试 可能我哪里写错了,谢谢

你直接用 ide 把所有,omitempty 删掉也行

如果我没理解错,这是 protobuffer 自己的特性,任何语言版本的 protobuffer 都会这样省略 0 值来减少传输。

可能需要关注你 client 端为什么反序列化出来没有这个字段。按理说,它反序列化时也会把零值自动填回来,该有的字段还是有的。
所以需要你补充解释「 api 请求 rpc server 出来的时候零值的字段是不存在的」

我去掉了,但是零值的字段还是没有, 不知道怎么回事

没有太理解 op 的意思,猜测是想 print 时候有零值字段?那应该从打印函数着手,我提供一个序列化为 json 的做法

go <br> var data bytes.Buffer<br> var jsonMarshal = &amp;jsonpb.Marshaler{<br> EnumsAsInts: false,<br> EmitDefaults: true,<br> Indent: "",<br> OrigName: false,<br> AnyResolver: nil,<br> }<br> err := jsonMarshal.Marshal(&amp;data, pb)<br> if err != nil {<br> return err<br> }<br>

好了,谢谢,我在 server 端去掉的,应该在 client 端去掉。是我没理解透彻,谢谢指导

好了,谢谢,我在 server 端去掉的,应该在 client 端去掉。是我没理解透彻,谢谢指导

可以了 谢谢

在Golang中使用proto3时,过滤零值(zero values)是一个常见的需求,尤其是在序列化和反序列化protobuf消息时。Proto3的默认行为是不会将零值字段包含在序列化后的数据中。这种行为有助于减少数据的大小并提升效率。

对于基本数据类型(如int32, float, bool等),零值分别是0, 0.0, false等。对于字符串类型,空字符串("")被视为零值。对于消息类型,未设置的字段(即未明确赋值的字段)也被视为零值。

如果你希望在序列化时包含某些零值字段,可以通过以下几种方式实现:

  1. 使用oneof:如果字段的值是可选的,并且你希望区分字段是否设置(即使设置为零值),可以使用oneof关键字。

  2. 自定义序列化逻辑:在序列化之前,手动检查字段值,并根据需要设置一些标志位或包装类型,以区分零值和未设置的情况。

  3. 使用Wrapper类型:对于基本数据类型,protobuf提供了Wrapper类型(如google.protobuf.Int32Value),这些类型可以显式地表示字段是否被设置。

请注意,修改protobuf的默认行为(即包含零值字段)可能会增加序列化后的数据大小,并可能影响性能。因此,在设计protobuf消息时,应仔细考虑是否需要包含零值字段,并在必要时使用上述技术。

希望这些信息对你有所帮助!如果有更多问题,欢迎继续讨论。

回到顶部