protoc генерирует значение вместо указателя (Go)

Проблема:

У меня в корневом каталоге есть 2 файла. Я использую Makefile для генерации кода Go из файлов .proto.

Но поле языка в структуре Video - это значение, а не указатель на значение. А поле субтитров в структуре Video - это массив значений, а не массив указателей на значение.

Вопрос:

Как я могу заставить протокол генерировать указатель на значение?

video.pb.go

type Video struct {
    state protoimpl.MessageState
    sizeCache protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    Id        string              `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
    Title     string              `protobuf:"bytes,2,opt,name=title,proto3" json:"title,omitempty"`

    // I need *language.ISO639_1 below
    Languages language.ISO639_1   `protobuf:"varint,3,opt,name=languages,proto3,enum=language.ISO639_1" json:"languages,omitempty"`

    // I need []*language.ISO639_1 below
    Subtitles []language.ISO639_1 `protobuf:"varint,4,rep,packed,name=subtitles,proto3,enum=language.ISO639_1" json:"subtitles,omitempty"`
}

Makefile

gen:
   # Video
   protoc -I. --go_out=plugins=grpc,paths=source_relative:video video.proto

   # Language
   protoc -I. --go_out=plugins=grpc,paths=source_relative:language language.proto

language.proto

syntax = "proto3";

package language;

option go_package = "example.com/group/repo/language;language";

enum ISO639_1 {
    UNKNOWN = 0;
    zh      = 1;
}

video.proto

syntax = "proto3";

package video;

import "language.proto";

option go_package = "example.com/group/repo/video;video";

message Video {
             string            id        = 1;
             string            title     = 2;
             language.ISO639_1 language  = 3;
    repeated language.ISO639_1 subtitles = 4;
}

версия протокола: libprotoc 3.11.4


person Klimbo    schedule 18.06.2020    source источник
comment
Может быть, дубликат this?   -  person blackgreen    schedule 18.06.2020
comment
@blackgreen Спасибо. Я это уже видел, но это не то. Проблема здесь в том, что протокол protoc не генерирует указатели, если файлы proto имеют разные имена пакетов. Если они совпадают - это будет указатель.   -  person Klimbo    schedule 18.06.2020
comment
Но у меня есть много мест, где мне нужен язык, поэтому я решил переместить его в отдельный прото-файл. Но я столкнулся с этим странным поведением   -  person Klimbo    schedule 18.06.2020
comment
Я не совсем уверен, чего вы пытаетесь достичь. Какая польза от указателя в формате обмена данными? По сути, вы пытаетесь сказать: «Привет, данные, которые я хочу передать, находятся на исходной машине по адресу 0x ...!»   -  person Markus W Mahlberg    schedule 20.06.2020


Ответы (1)


Начиная с proto3 версии 3.12, функция присутствия поля поддерживается экспериментально, что означает, что вы снова можете использовать ключевое слово optional, как и proto2.

Вы можете добиться этого, передав флаг --experimental_allow_proto3_optional в protoc при создании файлов pb.go (убедитесь, что вы используете достаточно новую версию protoc и protoc-gen-go для поддержки этой экспериментальной функции).

Итак, учитывая этот псевдо-.proto файл:

enum ISO639_1 {
    UNKNOWN = 0;
    zh      = 1;
}

message Video {
    string            id        = 1;
    string            title     = 2;

    optional ISO639_1 language  = 3;
    repeated ISO639_1 subtitles = 4;
}

Вы должны получить сгенерированную структуру с:

type Video struct {
    state         protoimpl.MessageState
    sizeCache     protoimpl.SizeCache
    unknownFields protoimpl.UnknownFields

    Language  *ISO639_1  `protobuf:"varint,3,opt,name=language,proto3,enum=grpctrace.ISO639_1,oneof" json:"language,omitempty"`
    Subtitles []ISO639_1 `protobuf:"varint,4,rep,packed,name=subtitles,proto3,enum=grpctrace.ISO639_1" json:"subtitles,omitempty"`
}

Хотя это решает вашу проблему с language, я не уверен, что вы сможете обойти поле repeated, чтобы получить значение указателя. Возможно, эта ветка может быть полезна - https://stackoverflow.com/a/25637833/13183366

person Matej G.    schedule 12.07.2020