Сегодня поговорим о недавно обновленном ходу.protobufистория. Процесс замечательный (твист) 😳
Два дня назад проектdependabotпакет чаевыхgithub.com/golang/protobufДоступна сV1.3.5обновитесь доV1.4.0
Round One
Я думал, что будет нормально обновиться напрямую, но без CI я нашел старую версию (V1.3.5) В тестовом коде используется сгенерированный код pbXXX_Size()метод расчета размера сообщения
в новой версии(v1.4.0)внутриpanicохватывать
Давайте посмотрим, чем они отличаются:
Для упрощения используем официальный файл protohelloworld.proto
СозданV1.3.5версия файла pb
curl -O https://raw.githubusercontent.com/grpc/grpc-go/master/examples/helloworld/helloworld/helloworld.proto
brew install protobuf
GO111MODULE=on go get -u github.com/golang/protobuf/protoc-gen-go@v1.3.5
protoc --go_out=plugins=grpc:. helloworld.proto
заменить сноваgithub.com/golang/protobuf/protoc-gen-go@v1.4.0, создать новую версию pb-файла
найтиXXX_Sizeфункция
В старой версии проблем нет
// helloword.pb.go
func (m *HelloRequest) XXX_Size() int {
return xxx_messageInfo_HelloRequest.Size(m)
}
var xxx_messageInfo_HelloRequest proto.InternalMessageInfo
// github.com/golang/protobuf@v1.3.5/proto/table_marshal.go
func (a *InternalMessageInfo) Size(msg Message) int {
В новой версии файла pb больше нетInternalMessageInfoТипы
Но его можно найти в исходниках, он заброшен.
// github.com/golang/protobuf@v1.4.0/proto/deprecated.go
// Deprecated: Do not use.
type InternalMessageInfo struct{}
func (*InternalMessageInfo) Size(Message) int { panic("not implemented") }
// 同样废弃的还有: DiscardUnknown, Marshal, Merge, Unmarshal
Как получить размер в новой версии кода?
Посмотрите пример в исходном коде,proto.Size(m Message) intможет быть реализован
InternalMessageInfoтакже стать интерфейсомtype Message = protoiface.MessageV1
этоInternalMessageInfoУстаревание также упоминается в обновлении версии, см. подробностиgenerated-code
ОК, метод замены, первый раунд окончен
Round Two
подожди, посмотри ещеgithub.com/golang/protobufдокумент, в котором упоминаетсяv1.4.0После версии код будет переданgoogle.golang.org/protobufОбслуживание репозитория, похоже, что Google получит все пакеты pb под свою организацию.
Тогда я просто положилgrpcИнструмент генерации также заменен прошлым!
GO111MODULE=on go get -u google.golang.org/protobuf/cmd/protoc-gen-go@v1.21.0
сгенерировать код снова
Новый инструмент автоматически предлагает добавить в файл proto:
option go_package = ".;helloworld";
на самом деле не удалось. . . намекать:
--go_out: protoc-gen-go: plugins are not supported; use 'protoc --go-grpc_out=...' to generate gRPC
Это новый флаг, попробуйте:
protoc --go-grpc_out=. helloworld.proto
Что? +1 за провал. . .
protoc-gen-go-grpc: program not found or is not executable
Please specify a program using absolute path or make sure the program is available in your PATH system variable
--go-grpc_out: protoc-gen-go-grpc: Plugin failed with status code 1.
protoc-gen-go-grpcЭто новый инструмент?
Искал, действительно есть этот инструмент, говорят, что новая версия будет использовать его для генерацииgrpc, в основном для лучшей поддержкиprotobuf reflection
Скажи это здесь:
прото-файл
serviceНеобходимостьgrpcизpluginЧтобы сгенерировать соответствующий pb-код Таким образом, у устаревших инструментов есть параметры--go_out=plugins=grpc:
Попробуйте установить:
GO111MODULE=on go get google.golang.org/protobuf/cmd/protoc-gen-go-grpc
Неудача +2. . .
go get google.golang.org/protobuf/cmd/protoc-gen-go-grpc: module google.golang.org/protobuf@upgrade found (v1.21.0), but does not contain package google.golang.org/protobuf/cmd/protoc-gen-go-grpc
goDoc имеетprotoc-gen-go-grpc,RepoНет, что это за операция?
Думаю, с этой проблемой должен столкнуться кто-то, и я нашел проблему:plugins are not supported:grpc
это былоgoogle.golang.org/protobufОн был выпущен первым, и он также содержит новую версиюprotoc-gen-go,
Просто больше не поддерживаетсяgrpcдля генерации требуется другой инструментprotoc-gen-go-grpc
Однако он не был выпущен и до сих порReviewсередина. . . (Конечно, на данный момент это не будет стабильной версией)
Однако чиновник также сказал, что старую сумку все еще можно использовать.github.com/golang/protobufизprotoc-gen-go-grpcсоздание инструментаgrpcкод
из-за старой сумки
protoc-gen-go-grpcВы все еще можете использовать новую сумкуprotoc-gen-go-grpcСгенерируйте код grpc вgengogrpc, Видетьcomment
Round Three
Что ж, тогда просто обновите protobuf, вызываемый в коде, доgoogle.golang.org/protobuf@v1.21.0, инструмент генерации кода по-прежнему использует старую версиюgithub.com/golang/protobuf/protoc-gen-go@v1.4.0Бар
Создайте файл pb снова, и, наконец, нет проблем, наконец-то мир
proto "github.com/golang/protobuf/proto"
grpc "google.golang.org/grpc"
codes "google.golang.org/grpc/codes"
status "google.golang.org/grpc/status"
protoreflect "google.golang.org/protobuf/reflect/protoreflect"
protoimpl "google.golang.org/protobuf/runtime/protoimpl"
Просто смотреть на сгенерированный код по-прежнему нужноimportстарая сумкаgithub.com/golang/protobuf, это всегда странно
После обновления это зависит от двухprotobufМешок. . .
Напоследок всем советую не торопиться, просто подождать и обновиться.
(Кроме того, ничего не нужно делать, чтобы перейти на новый пакет!)
Конечно, критическое изменение protobuf на этот раз по-прежнему имеет большое значение.Он не только делает отражение protobuf функцией первого уровня pb, но также предоставляет множество инструментов обработки.Подробности см. ниже:v1.21.0-release
Первый публичный аккаунт статьи: newbmiao
Рекомендуемое чтение:Серия Dig101-Go