Go Opaque API 迁移
Opaque API 是 Go 编程语言的 Protocol Buffers 实现的最新版本。旧版本现在称为 Open Struct API。 有关介绍,请参阅 Go Protobuf:发布 Opaque API 博客文章。
通过将 Protobuf Editions 功能 api_level
选项设置为其可能的值之一,可以按 proto 消息或按 .proto
文件为单位,逐步完成到 Opaque API 的迁移
API_OPEN
选择 Open Struct API;这是 2024 年 12 月之前的唯一 API。API_HYBRID
是 Open 和 Opaque 之间的步骤:Hybrid API 也包括访问器方法(因此您可以更新您的代码),但仍像以前一样导出结构字段。 没有性能差异;此 API 级别仅有助于迁移。API_OPAQUE
选择 Opaque API。
今天,默认值为 API_OPEN
,但即将到来的 Protobuf Edition 2024 会将默认值更改为 API_OPAQUE
。
要在 Edition 2024 之前使用 Opaque API,请按如下方式设置 api_level
edition = "2023";
package log;
import "google/protobuf/go_features.proto";
option features.(pb.go).api_level = API_OPAQUE;
message LogEntry { … }
在您可以将现有文件的 api_level
更改为 API_OPAQUE
之前,需要更新所有现有生成的 proto 代码的用法。 open2opaque
工具可以帮助您完成此操作。
为了您的方便,您还可以使用 protoc
命令行标志覆盖默认 API 级别
protoc […] --go_opt=default_api_level=API_OPAQUE
要为特定文件(而不是所有文件)覆盖默认 API 级别,请使用 apilevelM
映射标志(类似于 导入路径的 M
标志)
protoc […] --go_opt=apilevelMhello.proto=API_OPAQUE
命令行标志也适用于仍使用 proto2 或 proto3 语法的 .proto
文件,但是如果您想从 .proto
文件中选择 API 级别,则需要先将所述文件迁移到 editions。
自动化迁移
我们尽力使现有项目迁移到 Opaque API 尽可能容易:我们的 open2opaque 工具完成了大部分工作!
要安装迁移工具,请使用
go install google.golang.org/open2opaque@latest
注意
如果您在自动化迁移方法中遇到任何问题,请参阅 Opaque API:手动迁移 指南。项目准备
确保您的构建环境和项目正在使用足够新版本的 Protocol Buffers 和 Go Protobuf
从 protobuf 发布页面 更新 protobuf 编译器 (protoc) 到 29.0 或更高版本。
将 protobuf 编译器 Go 插件 (protoc-gen-go) 更新到 1.36.0 或更高版本
go install google.golang.org/protobuf/cmd/protoc-gen-go@latest
在每个项目中,更新
go.mod
文件以使用 1.36.0 或更高版本的 protobuf 模块go get google.golang.org/protobuf@latest
注意
如果您尚未导入google.golang.org/protobuf
,您可能仍在使用旧模块。 请参阅google.golang.org/protobuf
公告(来自 2020 年) 并在返回此页面之前迁移您的代码。
步骤 1. 切换到 Hybrid API
使用 open2opaque
工具将您的 .proto
文件切换到 Hybrid API
open2opaque setapi -api HYBRID $(find . -name "*.proto")
您现有的代码将继续构建。 Hybrid API 是 Open 和 Opaque API 之间的步骤,它添加了新的访问器方法,但保持结构字段可见。
步骤 2. open2opaque rewrite
要重写您的 Go 代码以使用 Opaque API,请运行 open2opaque rewrite
命令
open2opaque rewrite -levels=red github.com/robustirc/robustirc/...
您可以指定一个或多个 包或模式。
例如,如果您有如下代码
logEntry := &logpb.LogEntry{}
if req.IPAddress != nil {
logEntry.IPAddress = redactIP(req.IPAddress)
}
logEntry.BackendServer = proto.String(host)
该工具会将它重写为使用访问器
logEntry := &logpb.LogEntry{}
if req.HasIPAddress() {
logEntry.SetIPAddress(redactIP(req.GetIPAddress()))
}
logEntry.SetBackendServer(host)
另一个常见示例是使用结构字面量初始化 protobuf 消息
return &logpb.LogEntry{
BackendServer: proto.String(host),
}
在 Opaque API 中,等效的方法是使用 Builder
return logpb.LogEntry_builder{
BackendServer: proto.String(host),
}.Build()
该工具将其可用的重写分为不同的级别。 -levels=red
参数启用所有重写,包括那些需要人工审核的重写。 以下级别可用
- green: 安全重写(高置信度)。 包括该工具进行的大多数更改。 这些更改不需要仔细查看,甚至可以通过自动化提交,而无需任何人工监督。
- yellow: (合理的置信度)这些重写需要人工审核。 它们应该是正确的,但请审核它们。
- red: 潜在的危险重写,更改罕见且复杂的模式。 这些需要仔细的人工审核。 例如,当现有函数采用
*string
参数时,如果该函数旨在通过写入指针来更改字段值 (*foo = "value"
),则使用proto.String(msg.GetFoo())
的典型修复方法不起作用。
许多程序可以通过仅进行绿色更改即可完全迁移。 在您可以将 proto 消息或文件迁移到 Opaque API 之前,您需要完成所有级别的所有重写,此时您的代码中不再保留直接结构访问。
步骤 3. 迁移和验证
要完成迁移,请使用 open2opaque
工具将您的 .proto
文件切换到 Opaque API
open2opaque setapi -api OPAQUE $(find . -name "*.proto")
现在,任何尚未重写为 Opaque API 的剩余代码将不再编译。
运行您的单元测试、集成测试和其他验证步骤(如果有)。
有问题?疑问?
首先,查看 Opaque API 常见问题解答。 如果这不能回答您的问题或解决您的问题,请参阅 在哪里可以提出问题或报告问题?