Python2Go: o que aprendi reescrevendo um programa Python em Golang

Tive que reescrever um utilitário originalmente em Python para Go. Achei que seria bom registrar aqui o que eu aprendi no caminho.

NOTA: Continuo sendo um não-programador e não-desenvolvedor. Programo e desenvolvo porque senão ninguém resolve meus problemas.

O início de tudo

Há muitas eras atrás, escrevi um utilitário em Python que:

  • Lia um arquivo JSON com o resultado da execução de um aplicativo X “dockerizado”;
  • Destrichava o JSON;
  • Gerava um arquivo-texto com um “resumo executivo”;
  • Caso encontrasse alguma coisa “interessante”, notificava um canal no Teams.

Este utilitário deveria rodar em uma máquina do ambiente de produção (vamos chamar de máquina-alvo) que, por força de um software específico, tem como padrão o antediluviano Python 2.7 (não perguntem o motivo, apenas aceitem); como não precisava de nada além das bibliotecas padrão do Python 3, bastava executar o utlitário dentro de um container, conforme documentado na seção Run a single Python script do container oficial Python.

É fácil ver que esta situação levava a:

  • Execução de dois containers (o do aplicativo X e o do nosso utilitário), um após o outro;
  • Manutenção de duas imagens (a do aplicativo X e a do Python) no store do Docker;
  • Para fazer a comunicação entre os dois containers, precisávamos criar um arquivo JSON em disco, que se tornaria desnecessário ao final do processo.

A opção pela reescrita

Lá fui eu perguntar aos mecanismos de busca na internet se havia um SDK do Docker e, bom, tinha, sim, e com Python entre as linguagens suportadas. Fiz as mudanças necessárias no utilitário em Python para usar o SDK do Docker e, portanto, receber direto a saída do container do aplicativo X em vez de ler um JSON do disco. Ou seja, o utilitário passava a:

  • Rodar o container do aplicativo X e capturava a saída JSON;
  • Abrir o JSON, que estava carregado na memória, para gerar o “resumo executivo” e o aviso no canal do Teams.

Ou seja, o utilitário precisaria rodar com o Python instalado na máquina-alvo… que era 2.7. É, Python, não será você.

E como o SDK do Docker suporta oficialmente Go, o caminho natural foi usar Go: poderia gerar um executável compilado, que não precisaria de até mesmo ter Go instalado na máquina-alvo. Lá vamos nós reescrever um utilitário de umas 500 linhas pythônicas e “gopherizá-las”.

Como eu era novato em Go, passei um tempo lendo os tutoriais da página oficial; rapidamente aprendi o básico - hora de abrir o Visual Studio Code e instalar a extensão oficial Go.

Google, StackOverflow e código-fonte

Comecei a tropeçar aqui e ali; muitas coisas foram resolvidas com buscas rápidas no Google, outras muitas coisas foram resolvidas fazendo a busca correta no StackOverflow.

Só que um terceiro conjunto de muitas coisas só foram resolvidas recorrendo à leitura do código-fonte, tanto do próprio Go como dos módulos externos que eu utilizei - um problema, em especial, me exigiu ler o código-fonte do Docker SDK umas cinco vezes até entender o que eu deveria fazer. Nem sei em que repositório está o código-fonte do Python…

(Não perguntei ao ChatGPT, e isso era uma premissa pessoal da minha reescrita.)

O código em si

O código Python era estruturado em uma série de funções que recebiam um JSON, analisavam e saíam com as partes relevantes do “resumo executivo” e de uma eventual mensagem ao Teams; certamente foi um pouco de preciosismo da minha parte, então aproveitei para tornar o código mais “direto”… e se não fosse possível executar instruções antes dos laços if seria mais difícil ser direto.

Tive que tomar mais cuidado com o uso e reuso de variáveis e nomes de variáveis, especialmente fora de loops, várias vezes o Go reclamou desse hábito que eu tinha.

Achei bem mais fácil administrar módulos externos em Go do que em Python; em Python sempre acabava usando o Pipenv para gerar o requirements.txt, enquanto em Go aprendi rapidamente a usar e gostar do go mod.

Talvez eu tenha sido mal-acostumado pelo suporte incrível a JSON do Python, mas sofri um pouco até entender como funciona o suporte a JSON do Go.

Valeu a pena?

No meu caso, sim, porque cumpriu as condições que o código precisava cumprir. Mas talvez fosse melhor escrever diretamente em Go da próxima vez…


2023-06-06