Go: comandos CLI, parte 1
2021-01-02
Por curiosidade e vontade de aprender mais, fiquei intrigado com a quantidade de comandos disponíveis pela ferramenta CLI Go.
Este texto faz parte de uma série de 3 materiais no assunto:
- Parte 1:
bug
,build
,clean
edoc
- Parte 2:
env
,fix
,fmt
,generate
,get
einstall
- Parte 3:
list
,mod
,run
,test
,tool
,version
evet
Vale destacar que toda a documentação de referência utilizada foi baseada na versão 1.15.6 linux/amd64, obtida pela imagem oficial da linguagem Go no Docker Hub.
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
- https://maori.geek.nz/how-go-build-works-750bb2ba6d8e
- https://groups.google.com/g/golang-nuts/c/5KkBfRR8kik
- https://stackoverflow.com/questions/63059865/how-do-i-run-go-test-with-the-msan-option-on-ubuntu-18-04
- https://blog.golang.org/race-detector
- https://github.com/google/sanitizers/wiki/MemorySanitizer
- https://pt.stackoverflow.com/questions/3797/o-que-s%C3%A3o-e-onde-est%C3%A3o-a-stack-e-heap
- https://medium.com/martinomburajr/go-tools-the-compiler-part-1-assembly-language-and-go-ffc42cbf579d
- https://golang.org/doc/asm
- https://golang.org/cmd/asm/
- https://golang.org/doc/install/gccgo
- https://golang.org/cmd/link/