Go: comandos CLI, parte 1

Por curiosidade e vontade de aprender mais, fiquei intrigado com a quantidade de comandos disponíveis pela ferramenta CLI Go.

A linguagem de programação Go é muito bacana nesse ponto: preza pela simplicidade, porém traz consigo todo um conjunto de ferramentas bem diverso, para várias tarefas. Muitas linguagens também tem isso, porém poucas trazem tanta coisa de forma nativa, de brinde, pronta para uso.

Para quem não conhece, CLI é uma sigla em inglês que significa Command Line Interface, que em nosso idioma podemos traduzir como Interface de Linha de Comando. Num resumo, é uma forma de usar um programa pelo terminal, onde executamos comandos em linha e não por botões ou caixas de texto da interface gráfica do seu sistema operacional.

Como no dia a dia usamos poucos comandos (eu mesmo uso mais fmt, test, run e build), decidi me dedicar a aprender mais o que posso fazer com todos os comandos. Ao todo, a ferramenta go possui hoje (1.15.6 linux/amd) 17 comandos que, a partir deste artigo, vou tratando aos poucos, dado a quantidade de conhecimento agregado em cada comando.

Este texto é a parte 1 da série de artigos das ferramentas de linha de comando da linguagem Go, onde vou falar de go bug, go build, go clean e go doc.

Comando Descrição Resumo
bug start a bug report Instruções para abrir uma issue em golang.org/issue/new.
build compile packages and dependencies Cria binário.
clean remove object files and cached files Limpa arquivos desnecessários criados por packages.
doc show documentation for package or symbol Exibe documentação de um pacote.
env print Go environment information Exibe informações do ambiente atual.
fix update packages to use new APIs Atualiza o uso de APIs antigas no código.
fmt gofmt (reformat) package sources Aplica a formatação tradicional no código.
generate generate Go files by processing source Executa comandos descritos por diretivas no código.
get download and install packages and dependencies Baixa packages importados e suas dependências.
install compile and install packages and dependencies Compila e instala packages importados.
list list packages or modules Lista packages nomeados no projeto.
mod module maintenance Gerenciamento do uso de módulos no projeto.
run compile and run Go program Compila e executa código Go.
test test packages Executa testes dos packages importados.
tool run specified go tool Executa uma das ferramentas listadas por go tool.
version print Go version Exibe a versão de Go.
vet report likely mistakes in packages Examina código Go por erros não identificados por compiladores.

Mas para quê servem?

go bug

Abre o navegador padrão do seu sistema operacional para reportar um bug como registro oficial, fornecendo informações diversas sobre a versão de Go que está usando, variáveis de compilação, ambiente etc. É um atalho para reportar problemas.

go build [-o output] [-i] [build flags] [packages]

O comando faz a compilação do seu código, incluindo as dependências, e só. Isso exclui arquivos com extensão _test.go (padrão de arquivo de teste), ou seja, seus testes e os testes das dependências não farão parte da compilação por padrão.

A flag -o serve para definir o nome e caminho do arquivo binário criado pela compilação. É opcional, mas recomenda-se o uso. O comando go build -o ./abc ., por exemplo, instrui o compilador para criar no diretório atual o binário abc.

A flag -i serve para que a compilação instale os packages que são dependências do código.

Depois temos uma série de opções (build flags) para a compilação:

-a serve para forçar o rebuild de pacotes que já estão atualizados.

-n escreve os comandos no terminal, mas sem executá-los.

-p number define o número de programas que podem ser executados em paralelo. O padrão usado é o número de CPUs disponíveis. Para usá-la, basta substituir number pelo número desejado.

-race habilita detecção de race conditions no momento da compilação. Uma race condition ocorre quando dois ou mais processos são executados fora da ordem sequencial esperada, causando efeitos indesejados no programa. Se uma race condition é encontrada, o compilador escreve uma mensagem de atenção. Mesmo sendo um excelente recurso da linguagem, é preciso ser usado com prudência: uma vez habilitado, pode consumir 10 vezes o uso de CPU e memória. Recomendo a leitura deste texto para entender quando usar essa opção da forma mais adequada.

-msan ou memory sanitizer, serve para que o ato de compilação faça uso de sanitização de memória, que é um processo bem interessante: em casos de memória em pilha (stack) ou monte (heap), algumas alocações de memória podem ser lidas antes de serem escritas. O sanitizador de memória detecta esses casos onde pode haver efeitos na execução do programa. Recomendo a leitura deste texto para se aprofundar mais no assunto.

-v escreve o nome dos packages conforme são compilados.

-work se refere ao diretório temporário criado e usado na compilação. Go se utiliza de diretórios temporários para criar o binário na compilação para várias tarefas e os apaga depois da tarefa cumprida. Quando usamos esta flag, o comando exibe o local desse diretório e o preserva, sem apagá-lo.

-x escreve cada comando realizado no ato da compilação.

-asmflags '[pattern=]arg list' serve para operações à nível de máquina. Go possui partes de código Assembly em algumas de suas libs nativas e permite que o comando go build crie versões em Assembly do seu código. Isso quer dizer que a linguagem resolveu sua própria forma de “produzir” código Assembly, e não que tem toda a bagagem de outra linguagem, o que torna a linguagem “portátil”. Esta opção permite o uso de flags específicas no resultado desse tipo de compilação. Recomendo demais assistir esta apresentação do Rob Pike que explica a abordagem de Assembly desenvolvida na linguagem para se aprofundar mais no assunto.

-buildmode mode serve para indicar qual o modo de compilação (build) desejado. Cada modo de compilação vai gerar um resultado diferente. Todas as opções de modo de compilação podem ser lidas aqui.

-compiler name define qual compilador usar: gccgo (compilador baseado no GCC GNU Compiler) ou gc (compilador padrão da linguagem).

-gccgoflags '[pattern=]arg list' serve para enviar argumentos específicos quando usamos a opção -compiler gccgo.

-gcflags '[pattern=]arg list' por sua vez serve para argumentos específicos quando usamos a opção -compiler gc.

-installsuffix suffix serve como um sufixo para o nome do diretório onde vai ficar a instalação da compilação, para separar cada diretório de outros builds.

-ldflags '[pattern=]arg list' serve para inserir argumentos na fase de link (quando, durante a compilação, os arquivos obj estão prontos para se tornar um arquivo binário; veja a apresentação do Rob Pike citada acima para entender mais do assunto), ou seja, parâmetros a usar na preparação do arquivo binário. Esta opção é bem interessante, por isso recomendo a leitura deste texto e deste outro texto para entender as possibilidades oferecidas por esta opção.

-linkshared serve para uso junto da opção -buildmode=shared. Com esta opção, a compilação vai preparar o código que será “linkado” pelas libs compartilhadas geradas pelo buildmode citado.

-mod mode define qual o modo de download dos módulos, o que afeta o uso do arquivo go.mod: readonly (permite ao comando go somente a leitura do arquivo go.mod, falhando em qualquer tentativa de atualização), vendor (carrega as dependêndias de um diretório vendor ao invés de tentar fazer o download ou carregar do cache de módulos) ou mod (carrega os módulos do diretório de cache de módulos, mesmo se tiver um diretório vendor presente).

-modcacherw serve para deixar os diretórios de módulos recém criados no cache de leitura e escrita ao invés de somente leitura. Ou seja, guarda módulos em um diretório de cache de módulos com permissões de leitura e escrita.

-modfile file serve para usar outro arquivo de controle de módulos além do arquivo go.mod presente na raiz. Este uso é bem curioso porque ainda precisa de um arquivo go.mod na raiz, porém este não é utilizado, somente o arquivo inserido nesta opção. Seu uso também gera outro arquivo go.sum referente ao arquivo de módulo passado na opção.

-pkgdir dir serve para fornecer um diretório onde serão instalados e carregados todos os módulos, ao invés dos locais padrão. É útil para quando é necessário criar uma onfiguração fora do padrão do projeto.

-tags tag,list serve para passar uma lista de tags a ser usada no processo de compilação. Estas tags tem relação com as diretivas que podemos inserir no código. Para saber mais quais diretivas usar, leia com atenção este texto.

-trimpath serve para substituir todos os caminhos absolutos do sistema operacional presentes no binário final. No lugar, os caminhos são substituídos por go (no caso de packages nativos) ou path@version no caso de módulos, ou um caminho de import simples (no uso de GOPATH).

-toolexec 'cmd args' serve para evocar chamadas de outras ferramentas de go tool numa sequência, como vet, asm etc.

Vale destacar que muitas opções aqui presentes servem não só para o comando go build, mas também para go test, go run e go clean.

go clean [clean flags] [build flags] [packages]

O comando clean serve para limpeza de itens desnecessários, como arquivos, diretórios, cache entre outros, criados na compilação. Seu objetivo principal é de encontrar esses arquivos criados por outras ferramentas como Makefiles por exemplo, ou chamadas manuais de go build.

A flag -i habilita a remoção do arquivo ou binário instalado passado no comando, que teria sido criado pelo comando go install.

A flag -n é a execução silenciosa: escreve a execução dos comandos que seriam executados, sem executá-los de fato.

A flag -r habilita o uso recursivo do comando, incluindo as dependências dos packages importados no código.

A flag -x faz com que comandos de remoção sejam escritos conforme são executados.

A flag -cache faz com que o comando apague todo o conteúdo de cache de go build.

A flag -testcache expira todo o conteúdo de testes guardado no cache de go build.

A flag -modcache, por sua vez, apaga todo o conteúdo de cache de módulos, por completo.

go doc [-u] [-c] [package|[package.]symbol[.methodOrField]]

O comando go doc exibe a documentação do pacote, podendo mostrar a documentação completa ou parcial, dependendo da forma de uso do comando. Essa documentação é exatamente a explicação inserida no código (olha o valor de documentar bem o código que vocẽ faz!), fornecida em cada arquivo doc.go presente no repositório oficial da linguagem, só que offline, o que é bem útil!

Se usamos o comando sem passar o nome do package, apenas go doc, o comando busca a documentação do package do diretório onde se encontra.

O argumento de package passado é interpretado da forma como na sintaxe esperada da documentação da linguagem. Ou seja, go doc net/http exibe a documentação de http, assim como go doc net/http.Handler exibe somente a parte da documentação do type Handler contido no package http, e por aí vai. Note que o uso da inicial maiúscula em Handler é o que faz toda a diferença.

A flag -all exibe toda a documentação do package.

A flag -c torna o uso de case sensitive, ou seja, o parâmetro deve respeitar maiúsculas e minúsculas. go doc net/http.handler funciona, mas go doc -c net/http.handler retorna um erro de documentação não encontrada.

A flag -cmd trata a presença do package main como um package comum. Se ausente, o package main é ignorado na exibição.

A flag -short faz com que só seja exibida uma forma resumida da documentação.

A flag -src exibe todo o código fonte do package/símbolo usado. Isso inclui o código fonte, função, tipos, bem como outros detalhes não declarados.

A flag -u mostra a documentação de símbolos, métodos e campos não exportados.


E é isto! Se gostou, não deixe de acompanhar os próximos artigos para ver mais sobre outros comandos de CLI da linguagem Go! 😉


Referências

Davi Marcondes Moreira avatar
Sobre Davi Marcondes Moreira
Desenvolvedor de software, palestrante, evangelista de trabalho remoto e home office, amante de MTB/XCO e entusiasta de café. Ele/Dele.