OBSERVAÇÃO:este site foi descontinuado. O site será desativado após 31 de janeiro de 2023, e o tráfego será redirecionado para o novo site em https://protobuf.dev. Enquanto isso, as atualizações serão feitas apenas para protobuf.dev.

Perguntas frequentes

Mantenha tudo organizado com as coleções Salve e categorize o conteúdo com base nas suas preferências.

Versões

Qual é a diferença entre github.com/golang/protobuf e google.golang.org/protobuf?

O módulo github.com/golang/protobuf é a API do buffer de protocolo Go original.

O módulo google.golang.org/protobuf é uma versão atualizada dessa API, projetada para ter simplicidade, facilidade de uso e segurança. Os principais recursos da API atualizada são compatíveis com a reflexão e uma separação da API voltada para o usuário da implementação subjacente.

Recomendamos que você use google.golang.org/protobuf no novo código.

A versão v1.4.0 e versões mais recentes de github.com/golang/protobuf unem a nova implementação e permitem que os programas adotem a nova API de forma incremental. Por exemplo, os tipos conhecidos definidos em github.com/golang/protobuf/ptypes são apenas aliases daqueles definidos no módulo mais recente. Assim, google.golang.org/protobuf/types/known/emptypb e github.com/golang/protobuf/ptypes/empty podem ser usados de forma intercambiável.

O que são proto1, proto2 e proto3?

Estas são revisões da linguagem do buffer de protocolo. Isso é diferente da implementação (link em inglês) de Go dos protobufs.

  • proto3 é a versão atual da linguagem. Essa é a versão da linguagem mais usada. Incentivamos o novo código a usar o proto3.

  • proto2 é uma versão mais antiga da linguagem. Mesmo sendo substituído pelo proto3, o proto2 ainda é totalmente compatível.

  • proto1 é uma versão obsoleta da linguagem. Ele nunca foi lançado como código aberto. Consulte as Perguntas frequentes sobre buffers de protocolo para mais informações sobre proto1.

Existem vários tipos de Message. Qual devo usar?

Problemas comuns

"go install": working directory is not part of a module

No Go 1.15 e versões anteriores, você definiu a variável de ambiente GO111MODULE=on e está executando o comando go install fora de um diretório do módulo. Defina GO111MODULE=auto ou desmarque a variável de ambiente.

No Go 1.16 e versões mais recentes, go install pode ser invocado fora de um módulo especificando uma versão explícita: go install google.golang.org/protobuf/cmd/protoc-gen-go@latest

constant -1 overflows protoimpl.EnforceVersion

Você está usando um arquivo .pb.go gerado que requer uma versão mais recente do módulo "google.golang.org/protobuf".

Atualize para uma versão mais recente com:

go get -u google.golang.org/protobuf/proto

undefined: "github.com/golang/protobuf/proto".ProtoPackageIsVersion4

Você está usando um arquivo .pb.go gerado que requer uma versão mais recente do módulo "github.com/golang/protobuf".

Atualize para uma versão mais recente com:

go get -u github.com/golang/protobuf/proto

O que é um conflito de namespace do buffer de protocolo?

Todas as declarações de buffers de protocolo vinculadas a um binário Go são inseridas em um registro global.

Cada declaração protobuf (por exemplo, enumerações, valores de enum ou mensagens) tem um nome absoluto, que é a concatenação do nome do pacote com o nome relativo da declaração no arquivo de origem .proto (por exemplo, my.proto.package.MyMessage.NestedMessage). A linguagem protobuf presume que todas as declarações são universalmente exclusivas.

Se duas declarações protobuf vinculadas a um binário Go tiverem o mesmo nome, isso resultará em um conflito de namespace e será impossível para o registro resolver corretamente essa declaração por nome. Dependendo da versão dos protobufs em Go que estiverem sendo usados, ela vai entrar em pânico no momento da inicialização ou manter o conflito silenciosamente e levar a um possível bug mais tarde durante o tempo de execução.

Como corrigir um conflito de namespace de buffer de protocolo?

A maneira de corrigir um conflito de namespace depende do motivo do conflito.

Conflitos comuns de namespace:

  • Arquivos .proto fornecidos. Quando um único arquivo .proto é gerado em dois ou mais pacotes Go e vinculado ao mesmo binário Go, ele entra em conflito em cada declaração protobuf nos pacotes Go gerados. Isso normalmente ocorre quando um arquivo .proto é fornecido e um pacote Go é gerado com base nele, ou o próprio pacote Go é fornecido. Os usuários precisam evitar fornecedores e, em vez disso, depender de um pacote Go centralizado para esse arquivo .proto.

    • Se um arquivo .proto pertencer a uma parte externa e não tiver uma opção go_package, você vai precisar coordenar com o proprietário desse arquivo .proto para especificar um pacote Go centralizado de que todos podem confiar em uma variedade de usuários.
  • Nomes de pacote proto ausentes ou genéricos. Se um arquivo .proto não especificar um nome de pacote ou usar um nome de pacote muito genérico (por exemplo, "my_service"), haverá uma alta probabilidade de que declarações nesse arquivo entrem em conflito com outras declarações em outro lugar do universo. Recomendamos que todos os arquivos .proto tenham um nome de pacote escolhido de maneira universalmente exclusiva (por exemplo, prefixado com o nome de uma empresa).

    • Aviso: alterar retroativamente o nome do pacote em um arquivo .proto pode fazer com que o uso de campos ou mensagens de extensão armazenados em google.protobuf.Any pare de funcionar corretamente.

A partir da versão 1.26.0 do módulo google.golang.org/protobuf, um erro grave vai ser informado quando um programa Go for iniciado com vários nomes protobuf conflitantes vinculados a ele. Embora seja preferível que a origem do conflito seja corrigida, o erro fatal pode ser resolvido imediatamente de duas maneiras:

  1. No momento da compilação. O comportamento padrão para processar conflitos pode ser especificado durante a compilação com uma variável inicializada pelo vinculador: go build -ldflags "-X google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn"

  2. Na execução do programa. O comportamento para lidar com conflitos ao executar um binário Go específico pode ser definido com uma variável de ambiente: GOLANG_PROTOBUF_REGISTRATION_CONFLICT=warn ./main

Por que reflect.DeepEqual se comporta de maneira inesperada com mensagens protobuf?

Os tipos de mensagens de buffer de protocolo gerados incluem o estado interno que pode variar mesmo entre mensagens equivalentes.

Além disso, a função reflect.DeepEqual não reconhece a semântica das mensagens de buffer de protocolo e pode informar diferenças quando não houver nenhuma. Por exemplo, um campo que contém um mapa nil e outro que não tem nil é semanticamente equivalente, mas será relatado como desigual por reflect.DeepEqual.

Use a função proto.Equal para comparar valores de mensagem.

Em testes, também é possível usar o pacote "github.com/google/go-cmp/cmp" com a opção protocmp.Transform(). O pacote cmp pode comparar estruturas de dados arbitrárias, e cmp.Diff produz relatórios legíveis das diferenças entre os valores.

if diff := cmp.Diff(a, b, protocmp.Transform()); diff != "" {
  t.Errorf("unexpected difference:\n%v", diff)
}

Lei de Hyrum

O que é a lei da Hyrum e por que ela está nestas perguntas frequentes?

De acordo com a lei de Hyrum:

Com um número suficiente de usuários de uma API, não importa o que você promete no contrato: todos os comportamentos observáveis do sistema vão ser dependidos por alguém.

Um objetivo de design da versão mais recente da API de buffer de protocolo do Go é evitar, sempre que possível, fornecer comportamentos observáveis que não podemos prometer manter estáveis no futuro. É nossa filosofia que a instabilidade deliberada em áreas que não fazemos promessas é melhor do que a ilusão de estabilidade, somente para que isso mude no futuro depois que um projeto for potencialmente longo, dependendo da suposição falsa.

Por que o texto dos erros continua mudando?

Os testes que dependem do texto exato dos erros são instáveis e são corrompidos com frequência quando eles mudam. Para desencorajar o uso não seguro de texto de erro em testes, o texto de erros produzido por este módulo é deliberadamente instável.

Se você precisar identificar se um erro foi produzido pelo módulo protobuf, garantimos que todos os erros correspondam a proto.Error, de acordo com errors.Is.

Por que a saída de protojson continua mudando?

Não fazemos promessas sobre a estabilidade a longo prazo da implementação em Go do formato JSON para buffers de protocolo. A especificação só especifica o que é JSON válido, mas não fornece nenhuma especificação para um formato canônico para o modo como um marshaler precisa formatar exatamente uma determinada mensagem. Para evitar a ilusão de que a saída é estável, apresentamos deliberadamente pequenas diferenças para que as comparações de byte a byte provavelmente falhem.

Para ganhar algum grau de estabilidade da saída, recomendamos executar a saída por meio de um formatador JSON.

Por que a saída de prototext continua mudando?

Não fazemos promessas sobre a estabilidade a longo prazo da implementação do formato de texto. Não há especificação canônica do formato de texto protobuf e queremos preservar a capacidade de fazer melhorias na saída do pacote prototext no futuro. Como não prometemos estabilidade na saída do pacote, introduzimos deliberadamente a instabilidade para desencorajar os usuários a depender delas.

Para ter certo grau de estabilidade, recomendamos transmitir a saída de prototext pelo programa txtpbfmt. O formatador pode ser invocado diretamente no Go usando parser.Format.

Diversos

Como usar uma mensagem de buffer de protocolo como uma chave de hash?

A serialização canônica é necessária, em que a saída empacotada de uma mensagem de buffer de protocolo é estável ao longo do tempo. Infelizmente, não há uma especificação para serialização canônica no momento. Você vai precisar criar o seu ou encontrar uma maneira de evitar a necessidade.

Posso adicionar um novo recurso à implementação do buffer de protocolo do Go?

Talvez. Sempre gostamos de sugestões, mas temos muito cuidado ao adicionar novas coisas. Consulte as Perguntas frequentes sobre buffers de protocolo.

A implementação em Go dos buffers de protocolo se esforça para ser consistente com as outras implementações de linguagem. Por isso, tendemos a evitar recursos especialmente especializados em Go. Os recursos específicos de Go dificultam o objetivo de buffers de protocolo serem um formato de troca de dados de linguagem neutra.

A menos que sua ideia seja específica para a implementação do Go, participe do grupo de discussão de protobuf e sugira esse documento.

Caso você tenha uma ideia para a implementação do Go, registre um problema no nosso Issue Tracker: https://github.com/golang/protobuf/issues (link em inglês).

Posso adicionar uma opção a Marshal ou Unmarshal para personalizá-la?

Somente se essa opção existir em outras implementações (por exemplo, C++ e Java). A codificação de buffers de protocolo (binário, JSON e texto) precisa ser consistente entre as implementações. Portanto, um programa escrito em uma linguagem pode ler mensagens escritas em outro.

Não adicionaremos opções à implementação do Go que afetam a saída de dados por funções Marshal ou leem por funções Unmarshal, a menos que haja uma opção equivalente em pelo menos uma outra implementação compatível.

Posso personalizar o código gerado por protoc-gen-go?

Em geral, não. Os buffers de protocolo devem ser um formato de troca de dados independente de idioma, e as personalizações específicas da implementação são executadas de acordo com essa intent.