「这是我参与2022首次更文挑战的第7天,活动详情查看:2022首次更文挑战」。
介绍
我们很高兴地宣布针对协议缓冲区(Google 的数据交换格式(与语言无关))发布了 Go API 的主要修订版。
新 API 的动机
Rob Pike 在 2010 年 3 月宣布了 Go 的第一个协议缓冲区绑定。自第一次发布以来的十年中,该软件包与 Go 一起成长和发展。 其用户的需求也在增长。
许多人的程序想来使用反射来尝试、检查协议缓冲区消息内容。 reflect 包提供了 Go 类型和值的总览,但忽略了来自协议缓冲区类型系统的信息。 例如,我们可能想要编写一个函数来遍历日志条目并清除任何注释包含敏感数据的字段。 而注释不是 Go 类型系统的一部分。
另一个常见的需求是能够使用一些数据结构,但不是协议缓冲区编译器生成的那些数据结构,例如能够在编译时动态生成的类型。
我们观察的另外一个常见问题是: proto.Message 接口,它标识生成的消息类型的值,但是几乎没有描述这些类型的行为。 当用户创建实现该接口的类型(通常是通过在另一个结构中嵌入消息)并将这些类型的值传递给期望生成的消息值的函数时,程序可能会崩溃,或者出现意向不到的情况。
所有这三个问题都有一个共同的原因和一个共同的解决方案:Message 接口应该完全指定消息的行为,并且对 Message 值进行操作的函数应该自由地接受任何正确实现该接口的类型。
由于不可能在保持包 API 兼容的同时更改 Message 类型的现有定义,因此我们决定是时候开始处理新的、不兼容的 protobuf 模块的主要版本了。
今天,我们很高兴发布这个新模块。 我们希望你喜欢它。
反射
本次新实现的旗舰功能就是反射。 与 reflect 包提供 Go 类型和值的视图类似,google.golang.org/protobuf/reflect/protoreflect 包根据协议缓冲区类型系统提供值的视图。
对于这篇文章来说,对 protoreflect 包的完整描述可能会花很长时间,但让我们看看如何编写我们之前提到的日志清理功能。
首先,我们将编写一个 .proto 文件,定义 google.protobuf.FieldOptions 类型的扩展名,以便我们可以将字段注释为是否包含敏感信息。
syntax = "proto3";
import "google/protobuf/descriptor.proto";
package golang.example.policy;
extend google.protobuf.FieldOptions {
bool non_sensitive = 50000;
}
我们可以使用此选项将某些字段标记为不敏感
message MyMessage {
string public_name = 1 [(golang.example.policy.non_sensitive) = true];
}
接下来,我们将编写一个 Go 函数,它接受任意消息值并删除所有敏感字段。
// Redact clears every sensitive field in pb.
func Redact(pb proto.Message) {
// ...
}
\