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…