Go Enums Suck
O tratamento de enums no Go — na prática, apenas constantes inteiras com o auxiliar `iota` — é criticado como primitivo e inseguro em comparação com sistemas de enum ou tipos soma mais ricos em linguagens como Rust, Ada, Java ou até Pascal dos anos 1970. Os comentaristas debatem se o Go deveria adicionar enums verdadeiros, tipados com segurança, verificação de exaustividade e serialização mais segura, ou se sua filosofia minimalista, de “use ints e codegen/protobuf se precisar”, é um compromisso intencional e aceitável em favor da simplicidade e facilidade de uso no trabalho típico de web e backend. A discussão também aborda questões mais amplas de segurança de tipos, tratamento de erros e até onde uma linguagem deve ir ao adicionar recursos versus manter o núcleo pequeno e opinativo.
O que “enums” realmente são (enums vs tipos soma)
- Vários comentários distinguem enums clássicos (conjuntos finitos de constantes nomeadas, normalmente com base em inteiros e iteração/ordenação naturais) de tipos algébricos/tipos soma (variantes que podem conter dados estruturados e exigem correspondência de padrões).
- O
enumdo Rust é frequentemente citado como um tipo soma, não um “enum verdadeiro” no sentido tradicional, embora outros argumentem que essa distinção não é muito útil na prática. - Alguns veem tentativas de fundir enums e tipos soma em um único conceito como confusas e conceitualmente prejudiciais; outros se concentram no uso comum compartilhado de “escolha entre alternativas”.
A história atual de “enum” do Go
- O Go não tem uma palavra-chave dedicada para enum; o idiomático é
type T int+const (...)comiota. - Críticas:
- Não é um conjunto fechado; qualquer
intsubjacente pode ser construído, inclusive valores inválidos. - Sem representação de string embutida, verificação de exaustividade em
switch, ou prevenção de mistura de tipos de “enum” não relacionados além do tipo base. iotaé visto por alguns como perigoso para valores serializados, já que reordenar constantes altera silenciosamente as codificações numéricas.
- Não é um conjunto fechado; qualquer
- Defesas:
- Muitos acham
iotaconciso e muito conveniente, especialmente para flags de bits. - Alguns argumentam que os “enums” do Go são enums reais (constantes nomeadas de um tipo distinto) e que proteções extras não compensam a complexidade adicional.
- Passar
ints arbitrários é visto por alguns como claramente um bug do chamador, e não uma falha do sistema de tipos.
- Muitos acham
Contornos e ferramentas
- Padrões comuns: geradores de código (
go generate, ferramentas de terceiros, DSLs personalizadas) para adicionar conversão para string, integração com JSON/Protobuf e validação. - Enums do Protobuf são apontados como uma opção robusta se gRPC/Protobuf já estiver em uso, incluindo evolução segura e suporte entre linguagens.
Debate mais amplo sobre design de linguagem
- Um lado elogia o minimalismo do Go, builds rápidas, ferramentas simples e adequação “pé no chão” para trabalho de REST/DevOps.
- O outro lado chama a linguagem de primitiva e “sem noção” em sua resistência a recursos consagrados (generics, enums adequados, tipos soma, segurança contra nulos, restrições de tipo mais ricas).
- Comparações destacam que muitas linguagens antigas ou outras linguagens (Pascal, Ada, Rust, MLs, C#, Java) têm enums ou ADTs mais fortes, com exaustividade em tempo de compilação e melhor integração com sistemas de tipos.
Tratamento de erros e opcionalidade
- Alguns argumentam que retornos explícitos de
errorno Go são sensatos e tratam erros como fluxo de controle normal. - Outros preferem tipos soma no estilo
Result/Either/Optione veem a ausência desses construtos no Go (além da nulabilidade em todo lugar) como uma grande lacuna de design.