Linha de Comando

Os comandos em Go incluem um conjunto completo de ferramentas que abrangem documentação, formatação, verificação de código, compilação, testes, gerenciamento de dependências e muito mais, cobrindo todos os aspectos do desenvolvimento Go.
bug Reportar vulnerabilidades
build Compilar pacotes e dependências
clean Limpar arquivos objeto
doc Exibir documentação do código-fonte
env Exibir informações de variáveis de ambiente Go
fix Corrigir problemas de compatibilidade de API devido a mudanças de versão do Go
fmt Formatar código-fonte
generate Geração de código
get Adicionar dependências
install Instalar e compilar pacotes
list Comando de listagem de pacotes/módulos
mod Comando de manutenção de módulos
work Comando de manutenção de área de trabalho
run Compilar e executar
test Testar
tool Executar ferramentas Go especificadas
version Exibir informações de versão do Go
vet Verificar e reportar possíveis problemas no código-fonteEste artigo apenas descreve e introduz brevemente seu uso. Todo o conteúdo é referenciado da documentação oficial. Para saber mais detalhes, visite cmd/go.
help
O primeiro comando a conhecer é help, que permite ler o uso dos comandos. Existem dois usos: para obter informações breves de uso, você pode adicionar a flag -h após o comando especificado, por exemplo
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.Go exibirá concisamente o uso do comando e também indica que, para obter informações mais detalhadas, você precisa usar o comando help
$ go help env
usage: go env [-json] [-u] [-w] [var ...]
Env prints Go environment information.
By default env prints information as a shell script
(on Windows, a batch file). If one or more variable
names is given as arguments, env prints the value of
each named variable on its own line.
The -json flag prints the environment in JSON format
instead of as a shell script.
The -u flag requires one or more arguments and unsets
the default setting for the named environment variables,
if one has been set with 'go env -w'.
The -w flag requires one or more arguments of the
form NAME=VALUE and changes the default settings
of the named environment variables to the given values.
For more about environment variables, see 'go help environment'.Use bem o comando help para obter muitas informações sobre comandos.
doc
$ go doc -h
Usage of [go] doc:
go doc
go doc <pkg>
go doc <sym>[.<methodOrField>]
go doc [<pkg>.]<sym>[.<methodOrField>]
go doc [<pkg>.][<sym>.]<methodOrField>
go doc <pkg> <sym>[.<methodOrField>]
For more information run
go help doc
Flags:
-C dir
change to dir before running command
-all
show all documentation for package
-c symbol matching honors case (paths not affected)
-cmd
show symbols with package docs even if package is a command
-short
one-line representation for each symbol
-src
show source code for symbol
-u show unexported symbols as well as exportedO comando doc exibirá comentários de documentação para pacotes especificados, constantes, funções, tipos, variáveis, métodos e até campos de struct. Sem nenhum parâmetro, ele exibirá os comentários do pacote atual
$ go docVocê também pode especificar um pacote para visualizar, por exemplo, visualizar a documentação do pacote runtime
$ go doc runtime
package runtime // import "runtime"
Package runtime contains operations that interact with Go's runtime system,
such as functions to control goroutines. It also includes the low-level type
information used by the reflect package; see reflect's documentation for the
programmable interface to the run-time type system.
......Ou um tipo específico
$ go doc unsafe.Pointer
package unsafe // import "unsafe"
type Pointer *ArbitraryType
Pointer represents a pointer to an arbitrary type. There are four special
operations available for type Pointer that are not available for other
types:
- A pointer value of any type can be converted to a Pointer.
- A Pointer can be converted to a pointer value of any type.
- A uintptr can be converted to a Pointer.
- A Pointer can be converted to a uintptr.
...Ou uma função específica
$ go doc runtime.GC
package runtime // import "runtime"
func GC()
GC runs a garbage collection and blocks the caller until the garbage
collection is complete. It may also block the entire program.Possui as seguintes flags comuns
-u: Visualizar tipos privados-all: Visualizar toda a documentação de um pacote especificado-short: Apenas uma descrição breve em uma linha-src: Exibir código-fonte-cmd: Para pacotes que pertencem a comandos go, também exibir documentação de código dentro deles.
Por exemplo, visualizar a variável runtime.inf, que é uma variável não exportada
$ go doc -u runtime.inf
package runtime // import "runtime"
var inf = float64frombits(0x7FF0000000000000)Usar bem o comando doc pode ajudá-lo a ler documentação de forma mais conveniente.
Outra maneira de ler documentação de comandos é ler o código-fonte, pois a documentação de alguns comandos não é escrita de forma tão detalhada, enquanto o código-fonte tem explicações mais detalhadas. Como esses comandos são todos escritos em Go, a leitura é bastante conveniente. Esses comandos estão localizados no pacote src/cmd, onde cada subpacote é um comando separado, e a entrada está no arquivo cmd/go/main.go
func init() {
base.Go.Commands = []*base.Command{
bug.CmdBug,
work.CmdBuild,
clean.CmdClean,
doc.CmdDoc,
envcmd.CmdEnv,
fix.CmdFix,
fmtcmd.CmdFmt,
generate.CmdGenerate,
modget.CmdGet,
work.CmdInstall,
list.CmdList,
modcmd.CmdMod,
workcmd.CmdWork,
run.CmdRun,
test.CmdTest,
tool.CmdTool,
version.CmdVersion,
vet.CmdVet,
help.HelpBuildConstraint,
help.HelpBuildmode,
help.HelpC,
help.HelpCache,
help.HelpEnvironment,
help.HelpFileType,
modload.HelpGoMod,
help.HelpGopath,
get.HelpGopathGet,
modfetch.HelpGoproxy,
help.HelpImportPath,
modload.HelpModules,
modget.HelpModuleGet,
modfetch.HelpModuleAuth,
help.HelpPackages,
modfetch.HelpPrivate,
test.HelpTestflag,
test.HelpTestfunc,
modget.HelpVCS,
}
}Aqui você encontrará todos os subcomandos do Go e suas informações de documentação de ajuda.
bug
$ go help bug
usage: go bug
Bug opens the default browser and starts a new bug report.
The report includes useful system information.Este comando não possui parâmetros ou flags. Ele abrirá a página de issues do repositório github.com/golang/go no seu navegador padrão para facilitar o feedback de bugs, não tendo nenhuma outra função.
version
O comando version permite visualizar informações de versão do Go.
$ go version -h
usage: go version [-m] [-v] [file ...]Quando executado sem parâmetros, ele exibirá a versão atual da linguagem Go
$ go version
go version go1.21.0 windows/amd64Ele também aceita caminhos de arquivo como parâmetros e exibirá a versão do Go usada para compilar todos os arquivos binários identificáveis nesse caminho.
$ go version -v ./
buf.exe: go1.20.2
cobra-cli.exe: go1.21.0
dlv.exe: go1.20.2
goctl.exe: go1.20.2
goimports.exe: go1.20.2
golangci-lint.exe: go1.20.2
gopls.exe: go1.19.3
kratos.exe: go1.20.2
main.exe: go1.19.1
protoc-gen-go-grpc.exe: go1.20.2
protoc-gen-go-http.exe: go1.20.2
protoc-gen-go.exe: go1.20.2
protoc-gen-openapi.exe: go1.20.2
swag.exe: go1.21.0
wire.exe: go1.21.0O parâmetro -v especifica que o comando version tente exibir a versão do Go de arquivos não identificáveis, e o parâmetro -m exibirá informações de módulo e alguns parâmetros de compilação do arquivo binário. Aqui está um exemplo simples.
$ go version -v -m wire.exe
wire.exe: go1.21.0
path github.com/google/wire/cmd/wire
mod github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
dep github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k=
dep github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
dep golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b h1:NVD8gBK33xpdqCaZVVtd6OFJp+3dxkXuz7+U7KaVN6s=
build -buildmode=exe
build -compiler=gc
build DefaultGODEBUG=panicnil=1
build CGO_ENABLED=1
build CGO_CFLAGS=
build CGO_CPPFLAGS=
build CGO_CXXFLAGS=
build CGO_LDFLAGS=
build GOARCH=amd64
build GOOS=windows
build GOAMD64=v1O próprio go é um arquivo binário. Na verdade, quando executado sem parâmetros, go version exibe a versão da linguagem Go do seu próprio arquivo binário, pois toda a cadeia de ferramentas cmd/go é implementada pela própria linguagem Go.
env
O comando env permite visualizar todas as variáveis de ambiente do Go. Modificar essas variáveis de ambiente afetará o comportamento da cadeia de ferramentas Go.
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.Executar este comando sem parâmetros exibirá os valores de todas as variáveis de ambiente do Go
$ go env
set GO111MODULE=on
set GOARCH=amd64
...Usar o nome de uma variável de ambiente como parâmetro exibirá apenas o valor dessa variável
$ go env GO111MODULE
onAdicionar -json exibirá no formato JSON
$ go env -json
{
"AR": "ar",
"CC": "gcc",
......
}Usar a flag -w com parâmetro no formato var=value modificará permanentemente o valor de uma variável
$ go env -w GO111MODULE=onUsar a flag -u pode restaurar uma variável para seu valor padrão
$ go env -u GO111MODULEExecutar go help environment permite visualizar a descrição de cada variável de ambiente
$ go help environment
The go command and the tools it invokes consult environment variables
for configuration. If an environment variable is unset or empty, the go
command uses a sensible default setting. To see the effective setting of
the variable <NAME>, run 'go env <NAME>'. To change the default setting,
run 'go env -w <NAME>=<VALUE>'. Defaults changed using 'go env -w'
are recorded in a Go environment configuration file stored in the
per-user configuration directory, as reported by os.UserConfigDir.
The location of the configuration file can be changed by setting
the environment variable GOENV, and 'go env GOENV' prints the
effective location, but 'go env -w' cannot change the default location.
See 'go help env' for details.
General-purpose environment variables:
GO111MODULE
Controls whether the go command runs in module-aware mode or GOPATH mode.
May be "off", "on", or "auto".
See https://golang.org/ref/mod#mod-commands.
GCCGO
The gccgo command to run for 'go build -compiler=gccgo'.
GOARCH
The architecture, or processor, for which to compile code.
Examples are amd64, 386, arm, ppc64.
GOBIN
The directory where 'go install' will install a command.
GOCACHE
The directory where the go command will store cached
information for reuse in future builds.
......A seguir, apresentamos algumas variáveis de ambiente comumente usadas
GOVERSION
O valor desta variável de ambiente depende da versão da linguagem Go, e o número da versão vem do arquivo $GOROOT/VERSION, que registra a versão atual do Go e o tempo de compilação.
$ cat $GOROOT/VERSION
go1.21.3
time 2023-10-09T17:04:35ZO valor da variável runtime.Version é o mesmo que GOVERSION, e esta variável de ambiente não pode ser modificada.
GOENV
O diretório $GOROOT terá um arquivo de configuração padrão chamado go.env
$ cat $GOROOT/go.env
# This file contains the initial defaults for go command configuration.
# Values set by 'go env -w' and written to the user's go/env file override these.
# The environment overrides everything else.
# Use the Go module mirror and checksum database by default.
# See https://proxy.golang.org for details.
GOPROXY=https://proxy.golang.org,direct
GOSUMDB=sum.golang.org
# Automatically download newer toolchains as directed by go.mod files.
# See https://go.dev/doc/toolchain for details.
GOTOOLCHAIN=autoSeu formato é simplesmente key=value. Os valores das variáveis de ambiente modificados pelo comando go env -w key=value serão gravados no arquivo de configuração. No entanto, você pode não usar o arquivo de configuração padrão. A variável de ambiente GOENV pode especificar manualmente o endereço do arquivo de configuração env, e o valor da variável de ambiente GOENV só pode ser substituído pela variável de ambiente do sistema operacional e não pode ser modificado pelo comando go env -w.
GOHOSTARCH
Representa a arquitetura da CPU da máquina local, apenas para exibição. O valor desta variável de ambiente não é lido do arquivo de configuração e não pode ser modificado.
GOHOSTOS
Representa o sistema operacional da máquina local, apenas para exibição. O valor desta variável de ambiente não é lido do arquivo de configuração e não pode ser modificado.
GOOS
Durante a compilação, o valor de GOOS determinará em qual sistema de destino o código-fonte será compilado. O valor padrão é GOHOSTOS, que é o sistema operacional da máquina local. Possui as seguintes opções
linuxdarwinwindowsnetbsdaixandroid
Os sistemas operacionais suportados não se limitam a estes. Use o comando go tool dist list para visualizar todos os valores suportados
$ go tool dist list | awk -F '/' '{print $1}' | awk '!seen[$0]++'
aix
android
darwin
dragonfly
freebsd
illumos
ios
js
linux
netbsd
openbsd
plan9
solaris
wasip1
windowsGOARCH
Durante a compilação, o valor de GOARCH determinará qual arquitetura de CPU será usada para compilação. O valor padrão é GOHOSTARCH, que é a arquitetura da CPU da máquina local. Possui as seguintes opções
amd64386armppc64
As arquiteturas suportadas não se limitam a estas. Use o comando go tool dist list para visualizar todos os valores suportados
$ go tool dist list | awk -F '/' '{print $2}' | awk '!seen[$0]++'
ppc64
386
amd64
arm
arm64
riscv64
wasm
loong64
mips
mips64
mips64le
mipsle
ppc64le
s390xÉ importante notar que GOOS e GOARCH não podem ser combinados arbitrariamente. Alguns sistemas operacionais suportam apenas arquiteturas de CPU específicas.
GOROOT
GOROOT representa o diretório raiz da instalação da linguagem Go. O valor de GOROOT não pode ser modificado diretamente e só pode ser substituído pela variável de ambiente do sistema operacional.
$ ls $GOROOT -1
api
bin
codereview.cfg
CONTRIBUTING.md
doc
go.env
lib
LICENSE
misc
PATENTS
pkg
README.md
SECURITY.md
src
test
VERSIONNo diretório raiz, existem várias pastas ou arquivos importantes
lib: Armazena algumas dependências. Atualmente, há apenas uma biblioteca que contém informações de fuso horário de vários países, localizada em$GOROOT/lib/time. Os arquivos binários compilados não incluirão essas informações de fuso horário.pkg: Armazena algumas bibliotecas de ferramentas e arquivos de cabeçalho. Por exemplo, o comandogo toolprocurará os arquivos binários da cadeia de ferramentas Go no diretório$GOROOT/pkg/toolbin: Armazena arquivos binários. Por padrão, há apenas dois arquivos executáveis:goegofmt.$GOROOT/bindeve ser adicionado às variáveis do sistema, caso contrário, os comandos go não poderão ser usados.src: Armazena o código-fonte GoVERSION: Este arquivo armazena as informações de versão da linguagem Gogo.env: Este arquivo é o arquivo de configuraçãoenvpadrão
GOPATH
O valor padrão de GOPATH é $HOME/go. O valor desta variável de ambiente especifica onde procurar arquivos importados ao analisar instruções import. Nos primeiros dias, antes do gomod, GOPATH era usado especificamente para armazenar várias bibliotecas de terceiros. Sua estrutura é a seguinte
GOPATH=/home/user/go
/home/user/go/
src/
foo/
bar/ (go code in package bar)
x.go
quux/ (go code in package main)
y.go
bin/
quux (installed command)
pkg/
linux_amd64/
foo/
bar.a (installed package object)Após o surgimento do gomod, GOPATH tornou-se apenas um local para armazenar dependências baixadas pelo go get e arquivos binários baixados e compilados pelo go install. É importante notar que a localização de GOPATH não pode ser a mesma que GOROOT, caso contrário não funcionará.
$ go env GOBIN
warning: GOPATH set to GOROOT (/home/user/go) has no effectAté o momento em que escrevo este artigo, a versão da linguagem Go chegou à go1.21.3. Exceto por projetos muito antigos, basicamente ninguém usa mais gopath para gerenciar dependências.
GOBIN
GOBIN é usado para armazenar arquivos binários executáveis de terceiros baixados e compilados pelo go install. Seu valor padrão é $GOPATH/bin. Assim como $GOROOT/bin, este diretório deve ser adicionado às variáveis de ambiente do sistema operacional, caso contrário, os arquivos binários neste diretório não poderão ser usados.
GOMODCACHE
GOMODCACHE indica onde as dependências baixadas pelo go get são armazenadas. O valor padrão é $GOPATH/pkg/mod. O formato de armazenamento é o seguinte
$GOMODCACHE/domain/username/project@versionNo mesmo nível, haverá uma pasta chamada sumdb para armazenar informações relacionadas ao banco de dados de soma de verificação de dependências.
GOCACHE
Armazena informações de cache usadas para compilação. O valor padrão é $HOME/.cache/go-build. Um arquivo README será gerado neste diretório.
$ cat $(go env GOCACHE)/README
This directory holds cached build artifacts from the Go build system.
Run "go clean -cache" if the directory is getting too large.
Run "go clean -fuzzcache" to delete the fuzz cache.
See golang.org to learn more about Go.Cada build gerará muitos arquivos, e o Go armazenará esses arquivos em cache para reutilização na próxima compilação.
GOTEMPDIR
Usado para arquivos temporários gerados durante a compilação, como o arquivo binário temporário a ser executado pelo go run. Seu valor padrão é o diretório temporário especificado pelo sistema operacional: /tmp no Mac ou Linux, %TEMP% no Windows. Também pode ser modificado para uma localização especificada pelo usuário.
GO111MODULE
Esta variável de ambiente indica qual método usar para gerenciar dependências de projetos Go. Possui três valores disponíveis
off: Desativa o gomod, usa gopath e ignora todos os arquivosgo.modon: Usa gomod, não usa gopath (padrão).auto: Detecção automática. Se o arquivo do projeto contivergo.mod, usará gomod para gerenciamento
TIP
Por que se chama GO111MODULE e não simplesmente GOMODULE? Porque o gomod foi introduzido pela primeira vez na versão go1.11.
GOPROXY
Proxy de módulo Go. O valor padrão é https://proxy.golang.org,direct. As URLs são separadas por vírgula. direct significa usar diretamente o VCS para pular o proxy de módulo. O segundo só será executado se o primeiro não estiver acessível. Outra opção disponível é off, que proíbe o download de qualquer módulo. Além disso, GOPROXY também pode ser um endereço de arquivo, como
GOPROXY=file://$(go env GOMODCACHE)/cache/downloadUsar go get -x permite visualizar os comandos executados durante o processo de download de dependências, para saber se está usando proxy.
$ go get -x github.com/spf13/cast
# get https://goproxy.cn/github.com/@v/list
# get https://goproxy.cn/github.com/spf13/cast/@v/list
# get https://goproxy.cn/github.com/spf13/@v/list
# get https://goproxy.cn/github.com/spf13/@v/list: 404 Not Found (0.118s)
# get https://goproxy.cn/github.com/@v/list: 404 Not Found (0.197s)
# get https://goproxy.cn/github.com/spf13/cast/@v/list: 200 OK (0.257s)
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.info
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.info: 200 OK (0.013s)
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.mod
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.mod: 200 OK (0.015s)
# get https://goproxy.cn/sumdb/sum.golang.org/supported
# get https://goproxy.cn/sumdb/sum.golang.org/supported: 200 OK (0.064s)
# get https://goproxy.cn/sumdb/sum.golang.org/lookup/github.com/spf13/cast@v1.5.1
# get https://goproxy.cn/sumdb/sum.golang.org/lookup/github.com/spf13/cast@v1.5.1: 200 OK (0.014s)
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x079/736
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x079/736: 200 OK (0.016s)
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x068/334
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/1/266
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x068/334: 200 OK (0.023s)
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/1/266: 200 OK (0.028s)
go: downloading github.com/spf13/cast v1.5.1
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.zip
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.zip: 200 OK (0.024s)
go: added github.com/spf13/cast v1.5.1Usar proxy de módulo pode efetivamente melhorar a velocidade de download de módulos. Para usuários na China, basicamente não é possível acessar o proxy oficial padrão sem usar proxy. Atualmente, proxies de módulo de terceiros públicos e confiáveis incluem
https://proxy.golang.com.cn: Open source e também fornece serviços empresariaishttps://goproxy.cn: Fornecido e open source pela Qiniu Cloud
Claro, também há soluções open source para construir seu próprio proxy de módulo: goproxy
GOSUMDB
GOSUMDB é usado para definir o endereço do banco de dados de detecção de soma de verificação de bibliotecas de dependências. O padrão é sum.golang.org. Quando você define um proxy, o Go acessará o banco de dados de verificação através do proxy.
GOPRIVATE
A variável de ambiente GOPRIVATE é usada para definir bibliotecas privadas. As bibliotecas correspondentes não serão verificadas através do sumdb e não usarão proxy, sendo baixadas diretamente através do VCS. Suporta configurações de curinga, usando vírgulas como separador. Como mostrado abaixo, todas as dependências com sufixo corp.example.com e nomeadas github.com/gohper/myproject não usarão proxy ou sumdb.
GOPRIVATE=*.corp.example.com,github.com/gohper/myprojectTambém é possível definir diretamente um usuário ou organização específico
GOPRIVATE=github.com/gopher,github.com/myorganizationGONOPROXY
Indica quais dependências não precisam usar proxy. As regras são as mesmas de GOPRIVATE e substituirão GOPRIVATE.
GONOSUMDB
Indica quais dependências não precisam passar pelo banco de dados de soma de verificação. As regras são as mesmas de GOPRIVATE e substituirão GOPRIVATE.
GOINSECURE
Indica quais dependências devem ser baixadas diretamente usando VCS. As regras são as mesmas de GOPRIVATE e serão substituídas por GONOPROXY e GONOSUMDB.
GOVCS
Define o sistema de controle de versão para gerenciamento de módulos. O padrão é public:git|hg,private:all. Também é possível restringir VCS para domínios específicos, por exemplo
GOVCS=github.com:git,evil.com:off,*:git|hgNa restrição acima, github só pode usar git, evil.com não é permitido, e | pode representar múltiplos VCS. Se não houver restrições, pode ser definido da seguinte forma
GOVCS=*:allSe não for permitido o uso de nenhum VCS, pode ser definido da seguinte forma
GOVCS=*:offGOWORK
Define se a área de trabalho está habilitada. O padrão é vazio, ou seja, habilitado. Se definido como off, será desabilitado e ignorará todos os arquivos go.work.
GOTOOLDIR
Define a localização da cadeia de ferramentas Go a ser usada. O padrão é $GOROOT/pkg/tool, onde a cadeia de ferramentas padrão também está localizada.
GODEBUG
Define opções de depuração, controlando parcialmente o comportamento de execução de programas Go na forma de pares chave-valor, por exemplo
GODEBUG=http2client=0,http2server=0Essas configurações são para facilitar o retorno a comportamentos antigos do Go quando surgem mudanças incompatíveis durante atualizações de versão. Por exemplo, em 1.21, panic(nil) não é mais permitido. Para isso, a equipe oficial do Go registrou especificamente o GODEBUG History. Visite GODEBUG para saber mais detalhes.
CGO_ENABLED
Indica se o cgo está habilitado. O padrão é 1, ou seja, habilitado. Definir como 0 desabilita.
As variáveis de ambiente acima são as mais comumente usadas. Para algumas menos comuns, como CGO, WASM, etc., interessados podem aprender por conta própria.
build
O Go suporta dois tipos de compiladores: gccgo e gc. gcc é um antigo compilador c/c++ que suporta várias linguagens, incluindo Go. O último, gc, não significa garbage collector, mas sim Go Compiler. A linguagem Go completou sua auto-inicialização na versão go1.5. gc é um compilador escrito completamente em Go, e seu código-fonte está localizado no pacote cmd/compile. Como é totalmente implementado em Go, é muito conveniente para entender e aprender seu mecanismo interno. Por padrão, o compilador usa gc para compilação. A propósito, o depurador da linguagem Go também vem em dois tipos: gdb e dlv. O primeiro é um antigo depurador c/c++ que suporta várias linguagens, incluindo Go. O último é um depurador escrito em Go que oferece suporte mais amigável à linguagem Go. Também é open source e recomendado.
O comando build compila arquivos de código-fonte Go em arquivos binários executáveis. Você experimentará uma experiência de compilação bastante rápida, que é uma das características da linguagem Go.
$ go build -h
usage: go build [-o output] [build flags] [packages]
Run 'go help build' for details.Ele recebe três parâmetros: um é o caminho de saída do arquivo indicado pela flag -o, outro são as flags de compilação build flags usadas para definir o comportamento de compilação, e o último é o pacote a ser compilado. Este parâmetro deve ser colocado por último. Aqui está um exemplo simples sem usar flags de compilação.
# Windows
$ go build -o .\bin\golearn.exe golearn
# macOS / Linux
$ go build -o ./bin/golearn golearn./bin/golearn.exe representa o caminho de saída, e golearn representa o módulo a ser compilado. Também pode ser um arquivo de entrada ou um diretório. Por exemplo, o exemplo simples abaixo usa o arquivo de entrada main.go como alvo de compilação.
# Windows
$ go build -o .\bin\golearn.exe main.go
# macOS / Linux
$ go build -o ./bin/golearn main.goDurante a compilação, ele ignorará todos os arquivos que terminam com _test.go, pois por convenção são arquivos de teste.
Além disso, o comando build suporta muitas flags de compilação para controlar comportamentos durante a compilação.
-x: Exibe instruções detalhadas durante o processo de compilação-n: Similar a-x, mas apenas exibe essas instruções sem executá-las.-v: Exibe os pacotes compilados-p: Número de processos simultâneos durante a compilação-a: Força a reconstrução, mesmo que já esteja atualizado.-compiler: Especifica qual compilador usar,gccgoougc, sendo o último escrito em Go.-race: Habilita detecção de corrida-msan: Habilita análise de memória-asan: Habilita análise de endereço-cover: Habilita detecção de cobertura de código-buildmode: Especifica o modo de compilação, com opçõesarchive,c-archive,c-shared,default,shared,exe,pie,plugin.-pgo: Especifica arquivo pgo-trimpath: Remove prefixos de caminho de arquivos de código-fonte. Por exemplo, o caminho relativo/var/lib/go/src/main.goapós a remoção terá apenas o caminho relativo ao caminho do módulo/main.goquando obtido através deruntimeem tempo de execução. Habilitar esta opção aumentará significativamente o tempo de compilação, em cerca de 20-40%, dependendo do número de arquivos.-toolexec: Alguns comandos Go executados antes da compilação, no formato-toolexec 'cmd args'.-gcflags: Especifica algumas tags do compilador gc-gccgoflags: Especifica algumas tags do compilador gccgo-ldflags: Especifica algumas tags da ferramenta de link
Para parâmetros de transmissão como ldflags, você pode passar parâmetros como "-help" para obter seus valores possíveis, por exemplo
$ go build -ldflags -help
usage: link [options] main.o
-B note
add an ELF NT_GNU_BUILD_ID note when using ELF
-E entry
set entry symbol name
......Os acima são os mais comumente usados. Para outros menos comuns, você pode aprender por conta própria.
gcflags
Através de gcflags, você pode passar alguns parâmetros para o compilador gc para controlar comportamentos específicos. Seu formato de uso é -gcflags="pattern=args list", onde args list é a lista de parâmetros e pattern é o escopo de aplicação, com os seguintes valores disponíveis
main: Caminho do pacote de nível superior onde está o arquivo de entradaall: Módulo atual e todas as suas dependências no modo atualstd: Biblioteca padrãocmd: Aplica-se a todos os arquivos de código-fonte no pacotecmd- Curingas, como
.,./...,cmd/....
Esta regra de pattern se aplica a todas as flags que suportam este formato, como ldflags. Use o seguinte comando para visualizar os valores disponíveis de seus parâmetros
$ go build -gcflags -help
usage: compile [options] file.go...
-% debug non-static initializers
-+ compile runtime
-B disable bounds checking
-C disable printing of column numbers in error messages
-D path
set relative path for local imports
-E debug symbol export
-I directory
add directory to import search path
-K debug missing line numbers
-L also show actual source file location for error locations affected by //line directives
-N disable optimizations
-S print assembly listing
-V print version and exit
-W debug parse tree after type checking
......A seguir, apresentamos alguns parâmetros comumente usados
-S: Exibe a forma de assembly do código-N: Desabilita otimização de compilação-m: Exibe decisões de otimização-l: Desabilita inline de função-c: Número de processos simultâneos de compilação-dwarf: Gera símbolos DWARF
Por exemplo, se quiser visualizar a forma de assembly do código, você pode usar o parâmetro -S e também desabilitar otimização e inline para restaurar sua forma original, como segue
$ go build -trimpath -gcflags="-N -l -S" main.go
main.main STEXT size=171 args=0x0 locals=0x58 funcid=0x0 align=0x0
0x0000 00000 (./main.go:9) TEXT main.main(SB), ABIInternal, $88-0
0x0000 00000 (./main.go:9) CMPQ SP, 16(R14)
0x0004 00004 (./main.go:9) PCDATA $0, $-2
0x0004 00004 (./main.go:9) JLS 161
0x000a 00010 (./main.go:9) PCDATA $0, $-1
0x000a 00010 (./main.go:9) PUSHQ BP
0x000b 00011 (./main.go:9) MOVQ SP, BP
0x000e 00014 (./main.go:9) SUBQ $80, SP
0x0012 00018 (./main.go:9) FUNCDATA $0, gclocals·J5F+7Qw7O7ve2QcWC7DpeQ==(SB)
0x0012 00018 (./main.go:9) FUNCDATA $1, gclocals·bDfKCdmtOiGIuJz/x+yQyQ==(SB)
0x0012 00018 (./main.go:9) FUNCDATA $2, main.main.stkobj(SB)
0x0012 00018 (./main.go:10) MOVUPS X15, main..autotmp_0+40(SP)
0x0018 00024 (./main.go:10) LEAQ main..autotmp_0+40(SP), CX
0x001d 00029 (./main.go:10) MOVQ CX, main..autotmp_2+32(SP)ldflags
Através de ldflags, você pode passar alguns parâmetros para o linkador para controlar comportamentos específicos. Use o seguinte comando para visualizar todos os valores disponíveis de ldflags, que são quase vinte ou trinta.
$ go build -ldflags -help
usage: link [options] main.o
-B note
add an ELF NT_GNU_BUILD_ID note when using ELF
-E entry
set entry symbol name
-H type
set header type
-I linker
use linker as ELF dynamic linker
-L directory
add specified directory to library path
-R quantum
set address rounding quantum (default -1)
-T int
set the start address of text symbols (default -1)
-V print version and exit
-X definition
add string value definition of the form importpath.name=value
-a no-op (deprecated)
.....O parâmetro -X de ldflags é uma função muito prática que permite definir o valor de variáveis de string de pacotes especificados durante o link. Através desta função, podemos convenientemente injetar algumas metainformações durante a compilação. E como é apenas uma variável, também é conveniente obtê-la em tempo de execução. Aqui está um exemplo simples.
package main
import "fmt"
var (
Version string
)
func main() {
fmt.Println(Version)
}Executar comando
go build -ldflags "-X main.Version=$(git describe --always)" main.goApós a execução, exibirá a soma de verificação sha1 do commit git.
5e3fd7aAlguns outros parâmetros práticos incluem
-w: Não gera DWARF, que é uma informação conveniente para depuração de código-fonte.-s: Desabilita tabela de símbolos
Estes dois são geralmente usados juntos e podem reduzir significativamente o tamanho do arquivo binário compilado, em cerca de 40%-50%. A desvantagem também é óbvia: não é possível depurar. Aqui está um exemplo.
$ go build -ldflags="-w -s" main.goCompilação Cruzada
A compilação da linguagem Go tem duas características principais: a primeira é a rapidez, e a outra é a compilação cruzada. Compilação cruzada significa que você pode compilar localmente código de destino para outros sistemas, como compilar arquivos binários para linux ou darwin no windows, e vice-versa. Muitas linguagens suportam compilação cruzada, o que não é nada surpreendente, mas a compilação cruzada da linguagem Go é muito simples, requerendo apenas as seguintes etapas
- Defina a variável de ambiente GOOS para selecionar seu sistema operacional de destino
- Defina a variável de ambiente GOARCH para selecionar sua arquitetura de CPU de destino
- Use
go buildpara compilar como de costume
Todo o processo é muito rápido, sem necessidade de ferramentas ou configurações adicionais, e a velocidade é a mesma de sempre. Como mostrado abaixo
build_linux:
SET CGO_ENABLED=0
SET GOOS="linux"
SET GOARCH="amd64"
go build -o golearn main.go
build_mac:
SET CGO_ENABLED=0
SET GOOS="darwin"
SET GOARCH="amd64"
go build -o golearn main.go
build_win:
SET CGO_ENABLED=0
SET GOOS="win"
SET GOARCH="amd64"
go build -o golearn.exe main.go
.PHONY: build_linux \
build_mac \
build_winO primeiro passo SET CGO_ENABLED=0 desabilita o cgo. Uma vez que seu código use cgo, não será possível usar normalmente a compilação cruzada. O segundo passo SET GOOS define o sistema de destino, com opções linux, darwin, windows, netbsd. O terceiro passo define a arquitetura de CPU, SET GOARCH, com opções amd64, 386, arm, ppc64. O último passo é compilar como de costume.
Controle de Compilação
O comando build pode controlar a compilação através de tags, que existem no código-fonte como uma espécie de instrução. Veja um exemplo, arquivo product.go
// +build product
package main
import "fmt"
func main() {
fmt.Println("product")
}Arquivo debug.go
// +build debug
package main
import "fmt"
func main() {
fmt.Println("debug")
}Ambos têm uma instrução // +build, indicando em que circunstâncias serão compilados. Seu formato básico é
// +build tag1 tag2
package pkg_nameExistem algumas regras que devem ser seguidas
- Deve haver um espaço entre
//e+build - Deve estar acima da declaração do pacote
- Deve haver uma linha em branco entre ele e a declaração do pacote
Além disso, também pode alcançar controle lógico através de espaçamento simples: espaço representa OR, vírgula representa AND, ! representa NOT. Por exemplo
// +build windows linux
package pkg_nameIndica que o arquivo atual será compilado nas plataformas windows ou linux.
// +build windows,amd64,!cgo linux,i386,cgo
package pkg_nameEste exemplo indica que será compilado apenas na plataforma windows com arquitetura amd64 e sem cgo habilitado, ou na plataforma linux com arquitetura i386 e cgo habilitado. Se você simplesmente não quiser que um arquivo participe da compilação, pode usar ignore.
// +build ignore
package pkg_nameTambém pode haver múltiplas linhas de instruções
// +build windows
// +build amd64
package pkg_nameInstruções de múltiplas linhas são processadas de forma AND. Para tags como plataforma e arquitetura, o Go as passará automaticamente durante a compilação. Também podemos passar tags personalizadas. Usando os dois arquivos do início como exemplo
$ go build -tags="debug" . && ./golearn.exe
debug
$ go build -tags="product" . && ./golearn.exe
productComo você pode ver, a saída é diferente quando diferentes tags são passadas, alcançando o objetivo de controle de compilação.
run
Os comandos run e build ambos compilam o código-fonte, mas a diferença é que o comando run executa diretamente após a compilação. Para acelerar a compilação, o comando run não gera informações de depuração durante o processo de compilação, portanto não suporta depuração, e gera apenas um arquivo binário temporário, geralmente armazenado no diretório GOTEMPDIR, como /temp/go-build2822241271/b001/exe/main.exe.
$ go run -h
usage: go run [build flags] [-exec xprog] package [arguments...]
Run 'go help run' for details.Também suporta as flags de compilação do comando build e fornece um parâmetro -exec para especificar qual programa deve executar o arquivo binário. [arguments...] refere-se aos parâmetros de execução do programa. Aqui está um exemplo
package main
import (
"fmt"
"os"
)
var (
Version string
)
func main() {
fmt.Println(Version)
fmt.Println(os.Args[1:])
}Usar go run para executar
$ go run -ldflags="-X main.Version=$(git describe --always)" main.go hello
5e3fd7a
[hello]No geral, o uso é muito semelhante ao go build, então não vou me alongar mais.
tool
O comando tool em si não tem nenhuma função. Sua função é chamar diretamente as ferramentas no diretório cmd/, por exemplo, cmd/compile é o compilador embutido. Através de go tool, você pode chamar diretamente essas ferramentas sem precisar executar manualmente os arquivos binários dessas ferramentas.
$ go tool -h
usage: go tool [-n] command [args...]Use o parâmetro -n para imprimir todos os comandos suportados
$ go tool -n
addr2line
asm
buildid
cgo
compile
covdata
cover
doc
fix
link
nm
objdump
pack
pprof
test2json
trace
vetEssas ferramentas estão localizadas no diretório GOROOT/pkg/tool e são agrupadas de acordo com o sistema operacional e arquitetura de CPU, como segue.
$ ls $GOROOT/pkg/tool/windows_amd64/ -1
addr2line.exe*
asm.exe*
buildid.exe*
cgo.exe*
compile.exe*
covdata.exe*
cover.exe*
doc.exe*
fix.exe*
link.exe*
nm.exe*
objdump.exe*
pack.exe*
pprof.exe*
test2json.exe*
trace.exe*
vet.exe*Use o formato go doc cmd/command para visualizar o uso de cada comando, por exemplo
$ go doc cmd/compile
Usage:
go tool compile [flags] file...
The specified files must be Go source files and all part of the same package.
The same compiler is used for all target operating systems and architectures.
The GOOS and GOARCH environment variables set the desired target.
Flags:
-D path
Set relative path for local imports.
-I dir1 -I dir2
Search for imported packages in dir1, dir2, etc,
after consulting $GOROOT/pkg/$GOOS_$GOARCH.
-L
Show complete file path in error messages.
...As flags suportadas por cmd/compile são as mesmas mencionadas anteriormente para gcflags. A diferença entre go tool compile e go build é que o primeiro é apenas responsável pela compilação e só aceita arquivos como parâmetros, enquanto o último pode aceitar diretórios, pacotes e arquivos como parâmetros, e não apenas compila o código-fonte, mas também é responsável por linkar arquivos, limpar arquivos inúteis, etc. O primeiro é parte do último. Podemos imprimir os comandos executados durante o processo de build
$ go build -n main.go
#
# internal/goarch
#
mkdir -p $WORK\b004\
cat >$WORK\b004\importcfg << 'EOF' # internal
# import config
EOF
"/golang/pkg/tool/windows_amd64/compile.exe" -o "$WORK/b004/_pkg_.a" -trimpath "$WORK/b004=>" -p internal/goarch -std -+ -complete -buildid 3gunEkUExGdhOPa2rFsh/3gunEkUExGdhOPa2rFsh -goversion go1.21.0 -c=4 -nolocalimports -importcfg "$WORK/b004/importcfg" -pack "/golang/src/internal/goarch/goarch.go" "/golang/src/internal/goarch/goarch_amd64.go" "/golang/src/internal/goarch/zgoarch_amd64.go"
"/golang/pkg/tool/windows_amd64/buildid.exe" -w "$WORK/b004/_pkg_.a" # internal
...No processo, você pode ver que há /golang/pkg/tool/windows_amd64/compile.exe, que é a chamada do compilador. Além de compile, há muitas outras ferramentas que podem ser chamadas, e muitos comandos go são na verdade seus aliases.
clean
O comando clean é usado para limpar arquivos objeto gerados durante o processo de compilação
$ go clean -h
usage: go clean [clean flags] [build flags] [packages]
Run 'go help clean' for details.Suporta as seguintes flags
-i: Limpa os arquivos de arquivo ou binários correspondentes-n: Imprime os comandos que serão executados durante o processo de limpeza, mas não os executa-x: Imprime e executa os comandos que serão executados durante o processo de limpeza-r: Limpa recursivamente através doimport path-cache: Limpa todo o cache gerado pelogo build-testcache: Limpa todo o cache de teste gerado-modcache: Limpa todo o cache de módulos baixados-fuzzcache: Limpa o cache gerado pelofuzz test.
Quando se usa go tool compile, chama-se diretamente o comando do compilador, sem fazer muito trabalho de limpeza como o go build, o que gera arquivos objeto. Por exemplo, executar o seguinte comando
go tool compile -N -S -l main.goGerará um arquivo chamado main.o, que pode ser limpo usando o comando go clean. Ou use o parâmetro -n para imprimir os comandos que serão executados.
$ go clean -n
rm -f golearn golearn.exe golearn golearn.exe golearn.test golearn.test.exe golearn.test golearn.test.exe api api.exe main main.exeLimpar o cache de compilação removerá o cache de compilação gerado no diretório GOCACHE
$ go clean -cache -n
rm -r /cache/00 /cache/01 /cache/02Limpar o cache gerado pelo fuzz test, que é armazenado por padrão no diretório GOCACHE/fuzz/
$ go clean -fuzzcache -n
rm -rf /cache/fuzzfix
A linguagem Go já existe há dez anos até a escrita deste artigo. Durante o processo contínuo de atualização e modificação da linguagem, inevitavelmente surgem algumas incompatibilidades devido a mudanças de API. O comando fix foi criado para isso: ele detecta APIs obsoletas nos arquivos de código-fonte e as substitui por novas APIs.
$ go fix -h
usage: go fix [-fix list] [packages]
Run 'go help fix' for details.Suporta diretórios, nomes de arquivos e caminhos como parâmetros, e recebe a flag -fix para passar parâmetros indicando que tipo de modificação deve ser feita. Você pode visualizar os valores disponíveis através do comando go tool fix -help
$ go tool fix -help
usage: go tool fix [-diff] [-r fixname,...] [-force fixname,...] [path ...]
-diff
display diffs instead of rewriting files
-force string
force these fixes to run even if the code looks updated
-go string
go language version for files
-r string
restrict the rewrites to this comma-separated list
Available rewrites are:
buildtag
Remove +build comments from modules using Go 1.18 or later
cftype
Fixes initializers and casts of C.*Ref and JNI types
context
Change imports of golang.org/x/net/context to context
egl
Fixes initializers of EGLDisplay
eglconf
Fixes initializers of EGLConfig
gotypes
Change imports of golang.org/x/tools/go/{exact,types} to go/{constant,types}
jni
Fixes initializers of JNI's jobject and subtypes
netipv6zone
Adapt element key to IPAddr, UDPAddr or TCPAddr composite literals.
https://codereview.appspot.com/6849045/
printerconfig
Add element keys to Config composite literals.Aqui está um exemplo: o código-fonte usa o pacote golang.org/x/net/context
package main
import (
"fmt"
"golang.org/x/net/context"
)
func main() {
background := context.Background()
fmt.Println(background.Err())
}Use go fix para corrigir, substituindo pelo pacote context da biblioteca padrão. Podemos usar o seguinte comando para fazer a substituição
$ go fix -fix context main.goTambém é possível não substituir e apenas visualizar as mudanças no arquivo.
$ go tool fix -r context -diff main.go
main.go: fixed context
diff main.go fixed/main.go
--- main.go
+++ fixed/main.go
@@ -1,8 +1,8 @@
package main
import (
+ "context"
"fmt"
- "golang.org/x/net/context"
)
func main() {A linguagem Go existe há mais de dez anos e tem apenas nove parâmetros de substituição disponíveis, o que mostra que a compatibilidade é mantida razoavelmente bem.
fmt
O comando fmt é a ferramenta de formatação embutida da linguagem Go, usada para formatar arquivos de código-fonte Go.
$ go fmt -h
usage: go fmt [-n] [-x] [packages]
Run 'go help fmt' for details.Use o comando go doc gofmt para visualizar sua documentação detalhada
$ go doc cmd/gofmt
Gofmt formats Go programs. It uses tabs for indentation and blanks for
alignment. Alignment assumes that an editor is using a fixed-width font.
Usage:
gofmt [flags] [path ...]
The flags are:
-d
Do not print reformatted sources to standard output.
If a file's formatting is different than gofmt's, print diffs
to standard output.
-e
Print all (including spurious) errors.
-l
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, print its name
to standard output.
-r rule
Apply the rewrite rule to the source before reformatting.
-s
Try to simplify code (after applying the rewrite rule, if any).
-w
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, overwrite it
with gofmt's version. If an error occurred during overwriting,
the original file is restored from an automatic backup.gofmt usa tab para indentação e espaços para alinhamento. Por padrão, o código formatado será exibido na saída padrão, não sobrescrevendo o arquivo original. O comando go fmt na verdade usa o comando gofmt, que é um arquivo binário independente localizado no diretório GOROOT/bin.
$ ls $GOROOT/bin -1
go.exe*
gofmt.exe*Adicionar a flag -n ao comando go fmt permite saber quais comandos serão executados.
$ go fmt main.go
/golang/bin/gofmt.exe -l -w main.goComo você pode ver, go fmt é na verdade um alias de gofmt -l -w. O comando gofmt possui os seguintes parâmetros
-d: Exibe as diferenças antes e depois da formatação-e: Exibe todos os erros-l: Exibe os nomes dos arquivos que foram modificados-r: Aplica regras de formatação-s: Tenta simplificar o código-w: Sobrescreve o arquivo de origem. Se ocorrer um erro, restaura o backup
Suponha que agora tenhamos o seguinte arquivo de código-fonte
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")}Use o parâmetro -d para visualizar as mudanças
$ gofmt -d main.go
diff main.go.orig main.go
--- main.go.orig
+++ main.go
@@ -3,5 +3,5 @@
import "fmt"
func main() {
-fmt.Println("hello world!")}
-
+ fmt.Println("hello world!")
+}O parâmetro -l exibirá os nomes dos arquivos que serão modificados
$ gofmt -l .
main.goSe houver erros de sintaxe, o parâmetro -e pode exibir de forma mais detalhada
$ gofmt -d -e main.go
main.go:6:27: missing ',' in argument list
main.go:6:28: expected operand, found newline
main.go:7:2: expected ')', found 'EOF'
main.go:7:2: expected ';', found 'EOF'
main.go:7:2: expected ';', found 'EOF'
main.go:7:2: expected '}', found 'EOF'
main.go:7:2: missing ',' in argument list-w aplicará as modificações ao arquivo de origem
$ gofmt -l -w .
main.go
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")
}Você pode notar que, como ferramenta de formatação, gofmt não fornece nenhuma configuração personalizada. Em contraste, o formatador prettify para código js fornece muitas configurações para formatação de código. Isso reflete a atitude oficial do Go: não queira fazer personalizações, o estilo de código de todos deve ser o mesmo, pelo menos há uma vantagem: não é necessário se adaptar aos hábitos de outras pessoas ao ler código. No entanto, ainda保留了 uma personalização: as regras de substituição de código formatado podem ser personalizadas, no formato a seguir
pattern -> replacementPor exemplo, remover parênteses redundantes
(a) -> aVisualizar mudanças no arquivo
$ gofmt -r "(a) -> a" -d -l .
main.go
diff main.go.orig main.go
--- main.go.orig
+++ main.go
@@ -3,5 +3,5 @@
import "fmt"
func main() {
- fmt.Println(("hello world!"))
+ fmt.Println("hello world!")
}Como você pode ver, gofmt removerá os parênteses redundantes.
get
O comando get é absolutamente o mais usado durante o desenvolvimento Go. Sua função é baixar o código-fonte do pacote do endereço especificado para o diretório correspondente de GOMODCACHE.
$ go get -h
usage: go get [-t] [-u] [-v] [build flags] [packages]
Run 'go help get' for details.-u: Tenta atualizar a versão secundária e a versão de correção do pacote. Se envolver mudança de versão principal, comov1->v2, não será atualizado.-t: Atualiza a versão das dependências nos testes-v: Exibe os pacotes compilados, na verdade é um dos parâmetros debuild flags
Nos primeiros dias, go get era similar ao go install: baixava e compilava esses pacotes. No entanto, com o surgimento e aperfeiçoamento dos módulos Go, essa função foi gradualmente descontinuada. Agora, a função mais comum do comando get é baixar e resolver dependências para módulos Go. Portanto, você pode ver que o comando go get ainda suporta flags de compilação como build flags. E se você tentar usar go get fora de um módulo como usaria go install, ele avisará que este uso foi descontinuado.
$ go get github.com/wire/wire
go: go.mod file not found in current directory or any parent directory.
'go get' is no longer supported outside a module.
To build and install a command, use 'go install' with a version,
like 'go install example.com/cmd@latest'
For more information, see https://golang.org/doc/go-get-install-deprecation
or run 'go help get' or 'go help install'.Não se sabe por que essas descrições ainda são mantidas na documentação. Ao examinar o código-fonte do comando get, você descobrirá que ele mantém as flags antigas.
var (
getD = CmdGet.Flag.Bool("d", true, "")
getF = CmdGet.Flag.Bool("f", false, "")
getFix = CmdGet.Flag.Bool("fix", false, "")
getM = CmdGet.Flag.Bool("m", false, "")
getT = CmdGet.Flag.Bool("t", false, "")
getU upgradeFlag
getInsecure = CmdGet.Flag.Bool("insecure", false, "")
// -v is cfg.BuildV
)Voltando ao assunto, o comando get baixará o código-fonte do pacote especificado para o diretório de dependências global local, que é o diretório correspondente a GOCACHE, e então registrará as informações nos arquivos go.mod e go.sum. O primeiro é responsável por registrar a versão, e o segundo é responsável por registrar a soma de verificação sha1 para garantir segurança. O comando get é na verdade baseado em VCS, ou seja, sistema de controle de versão local, e suporta os seguintes
- git
- hg (Mercurial)
- bzr (Bazaar)
- svn
- fossil
Dentre eles, por padrão, apenas git e hg são suportados, podendo ser configurado em GOVCS, no formato a seguir
GOVCS=github.com:git,example.com:hg,*:git|hg,*:allGOVCS suporta apenas git e hg como VCS. Os outros três precisam ser configurados em GOPRIVATE.
O comando go get tem os seguintes usos: pode usar diretamente o endereço da dependência como parâmetro
$ go get golang.org/x/netTambém é possível especificar uma versão
$ go get golang.org/x/net@0.17.0Especificar a versão mais recente
$ go get golang.org/x/net@latestTentar atualizar a versão
$ go get -u golang.org/x/netRemover uma dependência
$ go get golang.org/x/net@noneOs usos acima são para gerenciar dependências comuns. Também pode ser usado para gerenciar dependências menos comuns, como atualizar a versão da linguagem Go
$ go get go@latest
go: updating go.mod requires go >= 1.21.3; switching to go1.21.3
go: downloading go1.21.3 (windows/amd64)
go: upgraded go 1.21.0 => 1.21.3Até mesmo pode ser usado para atualizar a versão da cadeia de ferramentas Go
$ go get toolchain@latestQuando você usa go get para atualizar as versões do Go e da cadeia de ferramentas, eles instalarão a nova versão do Go no diretório GOMODCACHE/golang.org/
$ ls $(go env GOMODCACHE)/golang.org -1
'toolchain@v0.0.1-go1.21.3.windows-amd64'/
x/Neste ponto, modificar manualmente GOROOT permitirá alternar para a versão especificada.
install
O comando install é similar ao comando get, ambos são usados para baixar dependências de terceiros, mas a diferença é que o comando get baixa o código-fonte, enquanto o comando install compila o código-fonte em um arquivo binário executável nativo. O caminho de armazenamento do arquivo binário é primeiro no diretório GOBIN e depois em GOPATH/bin. A principal função deste comando é baixar algumas ferramentas de linha de comando públicas de terceiros. Graças à velocidade de compilação e portabilidade da linguagem Go, não é necessário baixar arquivos binários, mas sim baixar o código-fonte e compilá-lo localmente.
$ go install -h
usage: go install [build flags] [packages]
Run 'go help install' for details.O comando install recebe flags de compilação e nomes de pacotes como parâmetros. Com o gomod habilitado, o nome do pacote deve incluir o número da versão. Por exemplo, baixar o depurador delve
$ go install -x github.com/go-delve/delve/cmd/dlv@latest
# get https://goproxy.cn/github.com/@v/list
# get https://goproxy.cn/github.com/go-delve/delve/cmd/@v/list
# get https://goproxy.cn/github.com/go-delve/delve/cmd/dlv/@v/list
# get https://goproxy.cn/github.com/go-delve/delve/@v/list
# get https://goproxy.cn/github.com/go-delve/@v/list
# get https://goproxy.cn/github.com/@v/list: 404 Not Found (0.014s)
# get https://goproxy.cn/github.com/go-delve/delve/cmd/@v/list: 404 Not Found (0.027s)
# get https://goproxy.cn/github.com/go-delve/delve/cmd/dlv/@v/list: 404 Not Found (0.027s)
# get https://goproxy.cn/github.com/go-delve/delve/@v/list: 200 OK (0.027s)
# get https://goproxy.cn/github.com/go-delve/@v/list: 404 Not Found (0.027s)
WORK=/home/user/tmp/go-build2033992495
mkdir -p $WORK/b001/
cat >/home/user/tmp/go-build2033992495/b001/importcfg.link << 'EOF' # internal
packagefile github.com/go-delve/delve/cmd/dlv=/home/user/.cache/go-build/f1/f11d552287458c0fce625abe50bf928c487064c36bbb1251ad8b1968772c3e4b-d
......
......
mkdir -p /home/wyh/gomod/bin/
mv $WORK/b001/exe/a.out /home/wyh/gomod/bin/dlv
rm -r $WORK/b001/Primeiro, ele baixará o código-fonte para o caminho armazenado em GOMODCACHE, o que é o mesmo que o comando get. Em seguida, muda para o diretório de trabalho temporário para compilá-lo. Após a compilação, move o arquivo binário para o diretório GOPATH/bin e finalmente exclui a pasta temporária. O comando install também tem uma restrição: o pacote baixado deve ser o pacote de entrada do projeto, ou seja, deve conter o arquivo de entrada main.go, caso contrário, avisará que não pode ser instalado. Por exemplo, usar go install para baixar o gin
$ go install -x github.com/gin-gonic/gin@latest
# get https://goproxy.cn/github.com/@v/list
# get https://goproxy.cn/github.com/gin-gonic/gin/@v/list
# get https://goproxy.cn/github.com/gin-gonic/@v/list
# get https://goproxy.cn/github.com/@v/list: 404 Not Found (0.022s)
# get https://goproxy.cn/github.com/gin-gonic/gin/@v/list: 200 OK (0.027s)
# get https://goproxy.cn/github.com/gin-gonic/@v/list: 404 Not Found (0.028s)
package github.com/gin-gonic/gin is not a main packagegin é uma biblioteca de dependência de framework web, não é uma ferramenta de linha de comando, naturalmente não tem arquivo de entrada, então a instalação falhará.
list
O comando list lista pacotes em locais especificados, um por linha, e suporta saída formatada personalizada. Suporta muitos parâmetros, e seu uso requer estar em um projeto que suporte gomod.
$ go list -h
usage: go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
Run 'go help list' for details.Os parâmetros suportados são os seguintes
-f: Parâmetro de formatação-json: Saída no formato json-compiled: Exibe todos os pacotes que serão compilados pelo compilador-deps: Exibe cada pacote e o nome de cada pacote do qual depende-test: Exibe o pacote de teste de cada pacote-e: Saída normal ao encontrar pacotes com erro-find: Não analisa as relações de dependência desses pacotes-export: Ao usar este parâmetro, define o valor do campoPackage.Exportda struct como o arquivo contendo as informações de exportação mais recentes do pacote especificado, e define o valor do campoPackage.BuildIDcomo oBuildIDdo pacote, principalmente para saída formatada.
Parâmetros de informações de módulo:
-m: Exibe módulos em vez de pacotes-versions: Exibe todas as informações disponíveis de um módulo-retracted: Exibe versões retraídas de um módulo
O parâmetro [packages] pode ser um nome de pacote especificado, ou um diretório, ou all, que significa qualquer lugar. Ao usar o parâmetro -m, all significa todas as dependências referenciadas pelo módulo atual.
Por exemplo, atualmente há apenas um arquivo main.go no diretório, e há apenas uma linha de código que exibe "hello world". Após executar go list -deps ., ele exibe todos os pacotes de dependência desde o projeto atual até fmt e suas referências.
$ ls
go.mod go.sum main.go
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
$ go list -deps .
internal/goarch
unsafe
internal/abi
internal/unsafeheader
internal/cpu
internal/bytealg
internal/coverage/rtcov
internal/godebugs
internal/goexperiment
internal/goos
runtime/internal/atomic
runtime/internal/math
runtime/internal/sys
runtime
......
......
path
io/fs
os
fmt
golearnOu exibe todas as dependências de módulo do projeto atual
$ go list -m all
golearn
cloud.google.com/go v0.26.0
github.com/246859/containers v0.0.1
github.com/246859/river v0.1.0 => D:\WorkSpace\Code\riverdb
github.com/BurntSushi/toml v0.3.1
github.com/Jleagle/steam-go v0.0.0-20230725082712-1053b441b1f2
github.com/Jleagle/unmarshal-go v0.0.0-20210227002040-694f544f9265
github.com/KyleBanks/depth v1.2.1
github.com/Microsoft/go-winio v0.6.1
github.com/PuerkitoBio/purell v1.1.1
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578
github.com/andeya/ameda v1.5.3
github.com/andeya/goutil v1.0.1
...format
A saída do comando list é por linha, e cada linha de saída é um pacote. A equipe oficial fornece o parâmetro -f para personalizar o formato de saída de linha. O valor que ele aceita é a sintaxe de template definida pelo pacote de motor de template template/text, por exemplo
-f "package {{ .Dir }} {{ .Name }}"Cada pacote iterado será passado na forma da seguinte struct, e todos os campos desta struct podem ser usados como parâmetros de template.
type Package struct {
Dir string // directory containing package sources
ImportPath string // import path of package in dir
ImportComment string // path in import comment on package statement
Name string // package name
Doc string // package documentation string
Target string // install path
Shlib string // the shared library that contains this package (only set when -linkshared)
Goroot bool // is this package in the Go root?
Standard bool // is this package part of the standard Go library?
Stale bool // would 'go install' do anything for this package?
StaleReason string // explanation for Stale==true
Root string // Go root or Go path dir containing this package
ConflictDir string // this directory shadows Dir in $GOPATH
BinaryOnly bool // binary-only package (no longer supported)
ForTest string // package is only for use in named test
Export string // file containing export data (when using -export)
BuildID string // build ID of the compiled package (when using -export)
Module *Module // info about package's containing module, if any (can be nil)
Match []string // command-line patterns matching this package
DepOnly bool // package is only a dependency, not explicitly listed
DefaultGODEBUG string // default GODEBUG setting, for main packages
// Source files
GoFiles []string // .go source files (excluding CgoFiles, TestGoFiles, XTestGoFiles)
CgoFiles []string // .go source files that import "C"
CompiledGoFiles []string // .go files presented to compiler (when using -compiled)
IgnoredGoFiles []string // .go source files ignored due to build constraints
IgnoredOtherFiles []string // non-.go source files ignored due to build constraints
CFiles []string // .c source files
CXXFiles []string // .cc, .cxx and .cpp source files
MFiles []string // .m source files
HFiles []string // .h, .hh, .hpp and .hxx source files
FFiles []string // .f, .F, .for and .f90 Fortran source files
SFiles []string // .s source files
SwigFiles []string // .swig files
SwigCXXFiles []string // .swigcxx files
SysoFiles []string // .syso object files to add to archive
TestGoFiles []string // _test.go files in package
XTestGoFiles []string // _test.go files outside package
// Embedded files
EmbedPatterns []string // //go:embed patterns
EmbedFiles []string // files matched by EmbedPatterns
TestEmbedPatterns []string // //go:embed patterns in TestGoFiles
TestEmbedFiles []string // files matched by TestEmbedPatterns
XTestEmbedPatterns []string // //go:embed patterns in XTestGoFiles
XTestEmbedFiles []string // files matched by XTestEmbedPatterns
// Cgo directives
CgoCFLAGS []string // cgo: flags for C compiler
CgoCPPFLAGS []string // cgo: flags for C preprocessor
CgoCXXFLAGS []string // cgo: flags for C++ compiler
CgoFFLAGS []string // cgo: flags for Fortran compiler
CgoLDFLAGS []string // cgo: flags for linker
CgoPkgConfig []string // cgo: pkg-config names
// Dependency information
Imports []string // import paths used by this package
ImportMap map[string]string // map from source import to ImportPath (identity entries omitted)
Deps []string // all (recursively) imported dependencies
TestImports []string // imports from TestGoFiles
XTestImports []string // imports from XTestGoFiles
// Error information
Incomplete bool // this package or a dependency has an error
Error *PackageError // error loading package
DepsErrors []*PackageError // errors loading dependencies
}
type PackageError struct {
ImportStack []string // shortest path from package named on command line to this one
Pos string // position of error (if present, file:line:col)
Err string // the error itself
}Se iterando módulos, será passado na forma da seguinte struct, e todos os seus campos também podem ser usados como parâmetros de template.
type Module struct {
Path string // module path
Query string // version query corresponding to this version
Version string // module version
Versions []string // available module versions
Replace *Module // replaced by this module
Time *time.Time // time version was created
Update *Module // available update (with -u)
Main bool // is this the main module?
Indirect bool // module is only indirectly needed by main module
Dir string // directory holding local copy of files, if any
GoMod string // path to go.mod file describing module, if any
GoVersion string // go version used in module
Retracted []string // retraction information, if any (with -retracted or -u)
Deprecated string // deprecation message, if any (with -u)
Error *ModuleError // error loading module
Origin any // provenance of module
Reuse bool // reuse of old module info is safe
}
type ModuleError struct {
Err string // the error itself
}Visualizar todos os pacotes
$ go list -f "package {{.Dir}} {{.Name}}" ./...
package /golearn main
package /golearn/app cmd
package /golearn/cmd cmd
package /golearn/docs docs
package /golearn/tool tool
package /golearn/tool_test toolVisualizar módulos
$ go list -m -f "mod {{.Path}} {{.Version}} {{.GoVersion}} {{.GoMod}}"
mod golearn 1.21.3 /golearn/go.modmod
go mod é um comando dedicado ao gerenciamento de módulos Go.
$ go mod help
Go mod provides access to operations on modules.
Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.
Usage:
go mod <command> [arguments]
The commands are:
download download modules to local cache
edit edit go.mod from tools or scripts
graph print module requirement graph
init initialize new module in current directory
tidy add missing and remove unused modules
vendor make vendored copy of dependencies
verify verify dependencies have expected content
why explain why packages or modules are needed
Use "go help mod <command>" for more information about a command.Possui os seguintes subcomandos
download: Baixa todas as dependências declaradas no arquivogo.modpara o cache localedit: Edita o arquivogo.mod. A interface de linha de comando fornecida é principalmente para uso por outras ferramentas ou scripts.init: Inicializa um projeto gomod no diretório atualtidy: Baixa dependências ausentes e remove dependências não utilizadasgraph: Exibe o gráfico de dependênciasverify: Verifica dependências locaiswhy: Explica por que esses módulos são dependentesvendor: Exporta dependências do projeto para o diretório vendor
init
$ go help mod init
usage: go mod init [module-path]O comando init é usado para inicializar um projeto gomod. Seu único parâmetro é o caminho do módulo, que será usado como base para que outras pessoas baixem suas dependências no futuro. Sua regra de nomenclatura geral é
domain_name/user_name/repo_namePor exemplo, como a maioria das pessoas coloca seus projetos no github, pode ser
github.com/jack/gotourNão é recomendado usar símbolos especiais como caminho de módulo. Aqui está um exemplo de uso
$ mkdir gotour
$ cd gotour
$ go mod init "github.com/jack/gotour"
go: creating new go.mod: module github.com/jack/gotourtidy
$ go help mod tidy
usage: go mod tidy [-e] [-v] [-x] [-go=version] [-compat=version]O comando tidy limpará as dependências não utilizadas no go.mod, ou seja, dependências que não são referenciadas, e baixará as dependências que são referenciadas mas não existem. Suporta os seguintes parâmetros
-v: Exibe as dependências de módulo que foram removidas-e: Ignora erros durante o processo e continua a execução-x: Exibe o processo de execução-go=version: Atualiza a versão do Go no arquivogo.mod-compat=version: Mantém quaisquer somas de verificação adicionais necessárias da versão principal do Go especificada para carregar com sucesso o gráfico de módulos, e se o comandogodesta versão carregar qualquer pacote importado de uma versão de módulo diferente, causará erro no tidy. Este parâmetro raramente é usado, geralmente causa erros apenas durante mudanças de versão. Você pode ver esta resposta no stackoverflow: go modules - go mod tidy error message: "but go 1.16 would select" - Stack Overflow
Veja um exemplo de uso
$ go mod tidy -v
unused github.com/246859/containers
unused github.com/246859/river
unused github.com/Jleagle/steam-go
unused github.com/Jleagle/unmarshal-go
unused github.com/KyleBanks/depth
unused github.com/Microsoft/go-winio
unused github.com/PuerkitoBio/purell
unused github.com/PuerkitoBio/urlesc
unused github.com/andeya/ameda
unused github.com/andeya/goutil
unused github.com/asaskevich/govalidator
unused github.com/buger/jsonparser
unused github.com/bwmarrin/snowflake
unused github.com/bytedance/go-tagexpr/v2
unused github.com/bytedance/sonic
unused github.com/cespare/xxhash/v2
unused github.com/chenzhuoyu/base64x
......download
$ go help mod download
usage: go mod download [-x] [-json] [-reuse=old.json] [modules]Embora o nome do comando download seja traduzido como download, ele apenas baixa as dependências para o cache de dependências local e não modifica o arquivo go.mod. Sua função é pré-baixar dependências para o cache de arquivos local. Se você quiser baixar uma dependência específica, é recomendado usar go get ou go mod tidy.
Aqui estão alguns exemplos de uso
$ go mod download -x gorm.io/gorm
# get https://goproxy.cn/gorm.io/gorm/@v/list
# get https://goproxy.cn/gorm.io/gorm/@v/list: 200 OK (0.084s)Se executado sem parâmetros, ele baixará todas as dependências que existem no arquivo go.mod mas não existem no cache de dependências local. Se não houver nada para baixar, ele exibirá
go: no module dependencies to downloadedit
$ go help mod edit
usage: go mod edit [editing flags] [-fmt|-print|-json] [go.mod]edit é uma interface de linha de comando para modificar o arquivo go.mod, geralmente usada por outros programas. Alguns editores e IDEs usam esses comandos para fornecer suporte a gomod. Suporta os seguintes parâmetros
-module: Modifica o caminho do módulo-go=version: Modifica a versão esperada do Go-require=path@version: Adiciona uma dependência-droprequire=path@version: Remove uma dependência-exclude=path@version: Adiciona uma dependência de exclusão-dropexclude=path@version: Remove uma dependência de exclusão-replace=old@version=new@version: Adiciona uma dependência de substituição-dropreplace=old@version: Remove uma dependência de substituição-retract=version: Adiciona um item de retração de versão-dropretract=version: Remove um item de retração de versão
Há também outros parâmetros para exibição
-print: Exibe o conteúdo do arquivo-json: Exibe no formato json
Por exemplo
$ go mod edit -print
module golearn
go 1.21.3
require (
github.com/dstgo/task v1.2.0
github.com/spf13/cast v1.5.1
github.com/swaggo/swag v1.16.2
golang.org/x/net v0.19.0
gorm.io/gorm v1.25.5
)graph
$ go help mod graph
usage: go mod graph [-go=version] [-x]O comando graph exibirá o gráfico de dependências do projeto atual. Sua legibilidade é muito ruim e na maioria das vezes não é destinado a leitura humana. Os resultados geralmente são processados e exibidos de forma visualizada. Cada linha é uma dependência, no formato a seguir
引用方 被引用方Por exemplo
golearn go@1.21.3Também suporta dois parâmetros
-go=version: Usa a versão do Go especificada para carregar o gráfico de dependências. O valor não pode ser menor que a versão no arquivogo.mod.-x: Exibe os comandos executados durante o processo.
Veja um exemplo de uso simples
$ go mod graph
golearn github.com/246859/containers@v0.0.1
golearn github.com/246859/river@v0.1.0
golearn github.com/Jleagle/steam-go@v0.0.0-20230725082712-1053b441b1f2
golearn github.com/Jleagle/unmarshal-go@v0.0.0-20210227002040-694f544f9265
golearn github.com/KyleBanks/depth@v1.2.1
golearn github.com/Microsoft/go-winio@v0.6.1
golearn github.com/PuerkitoBio/purell@v1.1.1
golearn github.com/PuerkitoBio/urlesc@v0.0.0-20170810143723-de5bf2ad4578
golearn github.com/andeya/ameda@v1.5.3
golearn github.com/andeya/goutil@v1.0.1
golearn github.com/asaskevich/govalidator@v0.0.0-20230301143203-a9d515a09cc2
golearn github.com/buger/jsonparser@v1.1.1
golearn github.com/bwmarrin/snowflake@v0.3.0
golearn github.com/bytedance/go-tagexpr/v2@v2.9.11
......vendor
$ go help mod vendor
usage: go mod vendor [-e] [-v] [-o outdir]vendor é uma alternativa ao gopath antes do lançamento do gomod. Cada projeto Go terá um diretório vendor, armazenando as dependências de cada projeto no formato domain/user/project, assim como o inchado node_module do Node.js, onde as dependências de cada projeto são armazenadas separadamente. Esta maneira de gerenciar dependências parece realmente estúpida agora, mas na época não havia uma solução melhor. A razão para manter o vendor é porque o Go mantém a promessa de compatibilidade com versões anteriores. Alguns projetos antigos, incluindo o código-fonte do Go, podem ainda estar usando vendor.
Voltando ao assunto, vendor é um subcomando do go mod que pode exportar as dependências globais referenciadas pelo módulo atual para o diretório vendor.
$ go mod vendor -h
usage: go mod vendor [-e] [-v] [-o outdir]
Run 'go help mod vendor' for details.Possui os seguintes parâmetros
-o: Especifica o caminho da pasta de saída-v: Exibe cada dependência-e: Não sai ao encontrar erros, continua
Veja um exemplo. Primeiro use go list -m all para visualizar as dependências referenciadas pelo projeto atual
$ go list -m all
github.com/dstgo/task
github.com/davecgh/go-spew v1.1.1
github.com/pkg/errors v0.9.1
github.com/pmezard/go-difflib v1.0.0
github.com/stretchr/objx v0.5.0
github.com/stretchr/testify v1.8.4
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405
gopkg.in/yaml.v3 v3.0.1Exporte para o diretório vendor atual
$ go mod vendor -v -e -o vendor
# github.com/davecgh/go-spew v1.1.1
## explicit
github.com/davecgh/go-spew/spew
# github.com/pkg/errors v0.9.1
## explicit
github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0
## explicit
github.com/pmezard/go-difflib/difflib
# github.com/stretchr/testify v1.8.4
## explicit; go 1.20
github.com/stretchr/testify/assert
# gopkg.in/yaml.v3 v3.0.1
## explicit
gopkg.in/yaml.v3A estrutura de diretórios após a exportação é a seguinte
└─vendor
├─github.com
│ ├─davecgh
│ │ └─go-spew
│ │ └─spew
│ ├─pkg
│ │ └─errors
│ ├─pmezard
│ │ └─go-difflib
│ │ └─difflib
│ └─stretchr
│ └─testify
│ └─assert
└─gopkg.in
| └─yaml.v3
|
|--modules.txtO modules.txt é o arquivo que descreve todas as dependências, semelhante ao atual go.mod.
verify
$ go help mod verify
usage: go mod verifyEste comando verificará se as dependências do projeto foram modificadas após serem baixadas para o local. Por exemplo, se não houver problemas, exibirá all modules verified
$ go mod verify
all modules verifiedCaso contrário, ele reportará onde ocorreram mudanças e terminará o comando com status anormal. Por exemplo
$ go mod verify
gorm.io/gorm v1.25.5: dir has been modified (/go/mod/libs/gorm.io/gorm@v1.25.5)why
$ go help mod why
usage: go mod why [-m] [-vendor] packages...Explica por que este pacote é dependente, na verdade exibe o gráfico de dependências relacionado a ele. Por exemplo
$ go mod why gorm.io/gorm
# gorm.io/gorm
golearn
gorm.io/gormPor padrão, apenas analisará as importações de main. Adicionar o parâmetro -m pode analisar a situação de importação de cada pacote.
work
O comando work é uma ferramenta de desenvolvimento local para gerenciamento de múltiplos módulos Go
$ go work help
Work provides access to operations on workspaces.
Note that support for workspaces is built into many other commands, not
just 'go work'.
The commands are:
edit edit go.work from tools or scripts
init initialize workspace file
sync sync workspace build list to modules
use add modules to workspace file
vendor make vendored copy of dependencies
Use "go help work <command>" for more information about a command.init
O subcomando init é usado para inicializar um workspace. Este comando criará um arquivo chamado go.work
$ go work init -h
usage: go work init [moddirs]
Run 'go help work init' for details.Recebe o parâmetro [moddirs] para especificar quais módulos serão gerenciados, por exemplo
$ go work init ./service ./apiuse
O subcomando use é usado para adicionar diretórios de módulos gerenciados ao go.work
$ go help work use
usage: go work use [-r] [moddirs]
Use provides a command-line interface for adding
directories, optionally recursively, to a go.work file.Recebe [moddirs] como parâmetro, e há uma flag -r que indica para pesquisar recursivamente por módulos no caminho [moddirs], por exemplo
$ go work use -r ./oss-api ./multi_modulesedit
A função do subcomando edit é a mesma de go mod edit, ambos são deixados para interfaces de linha de comando para outras ferramentas e scripts operarem.
$ go help work edit
usage: go work edit [editing flags] [go.work]
Edit provides a command-line interface for editing go.work,
for use primarily by tools or scripts. It only reads go.work;
it does not look up information about the modules involved.
If no file is specified, Edit looks for a go.work file in the current
directory and its parent directoriesOs parâmetros são os seguintes
-fmt: Formata o arquivogo.work-use,-dropuse: Adiciona e remove caminhos de módulo-replace=old[@v]=new[@v],-dropreplace=old[@v]=new[@v]: Usado para adicionar e remover módulos a serem substituídos-go,-toolchain=name: Especifica a versão do Go e a cadeia de ferramentas a ser usada-print: Imprime as modificações finais sem gravar de volta no arquivo-json: Exibe no formatojson, não pode ser usado com-printsimultaneamente. A estrutura de tipo correspondente é a seguintegotype GoWork struct { Go string Toolchain string Use []Use Replace []Replace } type Use struct { DiskPath string ModulePath string } type Replace struct { Old Module New Module } type Module struct { Path string Version string }
Alguns exemplos de uso são os seguintes: saída formatada
$ go work edit -fmt -print
go 1.22.0
use (
./ab/cd
./auth
./user
)Saída json
$ go work edit -fmt -json
{
"Go": "1.22.0",
"Use": [
{
"DiskPath": "./ab/cd"
},
{
"DiskPath": "./auth"
},
{
"DiskPath": "./user"
}
],
"Replace": null
}sync
O subcomando sync é usado para sincronizar a lista de módulos no go.work de volta aos vários módulos no workspace.
$ go help work sync
usage: go work sync
Sync syncs the workspace's build list back to the
workspace's modulesEste processo ocorre principalmente após a conclusão do desenvolvimento local, quando cada módulo já completou o trabalho de lançamento. Neste ponto, usar sync atualizará as dependências no go.mod de todos os módulos no workspace de acordo com as relações de dependência de cada módulo, eliminando a necessidade de atualização manual.
vendor
O comando vendor copiará todas as bibliotecas dependentes de todos os módulos no workspace para o diretório vendor.
$ go work help vendor
usage: go work vendor [-e] [-v] [-o outdir]A função é a mesma de go mod vendor, não vou me alongar mais.
vet
O comando vet é uma ferramenta de verificação estática de erros de código-fonte da linguagem Go, assim como ferramentas lint de outras linguagens, como Eslint.
$ go vet -h
usage: go vet [build flags] [-vettool prog] [vet flags] [packages]
Run 'go help vet' for details.
Run 'go tool vet help' for a full list of flags and analyzers.
Run 'go tool vet -help' for an overview.Vamos ver um exemplo simples. Existe o seguinte código-fonte
$ cat main.go
package main
import "fmt"
func main(){
fmt.Println("hello world!"
}Execute go vet sem parâmetros no mesmo diretório
$ go vet
vet: ./main.go:6:28: missing ',' before newline in argument list (and 1 more errors)vet reportará qual arquivo, qual linha e qual é o problema. Suporta flags de compilação como parâmetros, como -n e -x, e suporta pacotes, diretórios e nomes de arquivos como parâmetros.
$ go vet .
$ go vet main.go
$ go vet ./cmd
$ go vet runtimeUse o seguinte comando para visualizar seus parâmetros e explicações mais detalhados.
$ go tool vet help
vet is a tool for static analysis of Go programs.
vet examines Go source code and reports suspicious constructs,
such as Printf calls whose arguments do not align with the format
string. It uses heuristics that do not guarantee all reports are
genuine problems, but it can find errors not caught by the compilers.
Registered analyzers:
asmdecl report mismatches between assembly files and Go declarations
assign check for useless assignments
atomic check for common mistakes using the sync/atomic package
bools check for common mistakes involving boolean operators
buildtag check //go:build and // +build directives
......O comando go tool vet não pode ser usado diretamente para verificar código. Deve-se usar go vet. Os [vet flag] nos parâmetros do go vet suportam a configuração de analisadores de código. Os valores disponíveis são os seguintes
asmdecl 检查汇编文件是否与 go 声明不匹配
assign 检查是否有无用的变量
atomic 检查使用 sync/atomic 时是否破坏了原子性
bools 检查是否错误使用逻辑运算符
buildtag 检查 build tag
cgocall 检查违反 cgao 指针传递规则的行为
composites 检查未初始化的复合结构,比如 map,chan
copylocks 检查是否发生了锁的值复制
directive 检查 go 工具链指令
errorsas 检查是否向 errors.As 传递非指针类型或非 error 类型的值
framepointer 检查编译优化后的汇编代码是否在保存帧指针之前对其进行清除
httpresponse 检查是否错误使用 httpresponse
ifaceassert 检查接口到接口的类型断言
loopclosure 循环变量的引用问题
lostcancel context.WithCancel 没有使用 cancel 函数
nilfunc 检查函数和 nil 之间是否存在无用的比较
printf 检查 printf 的格式化参数是否正确
shift 检查是否有等于或超过整数宽度的移位
sigchanyzer 检查无缓冲的 chan os.Signal
slog 检查不合法的结构化日志调用
stdmethods 检查已知接口方法的签名是否正确
stringintconv 检查字符串整型转换
structtag 检查结构体 tag 是否正确
testinggoroutine 检查是否在测试中使用协程调用 testing.Fatal
tests 检查测试和示例的常见错误用法
timeformat 使用 (time.Time).Format 或 time.Parse 的时间格式是否正确
unmarshal 向 unmarshal 传递非指针或非接口类型
unreachable 检查不可到达的代码
unsafeptr 检查 uintptr 到 unsafe.Pointer 不正确转换
unusedresult 检查未使用的函数返回值Todos são analisadores que analisam um ponto específico. Por exemplo, o analisador timeformat verifica se a chamada de time.Format está em conformidade com a sintaxe correta. Por padrão, todos os analisadores acima serão habilitados. Para habilitar individualmente, use o seguinte formato
$ go vet -timeformat main.goPara desabilitar individualmente
$ go vet -timeformat=false main.goO código-fonte desses analisadores está localizado em cmd/vendor/golang.org/x/tools/go/analysis/passes. Cada analisador é uma armadilha comum na linguagem Go, por isso é altamente recomendado usar o comando vet para verificar seu código. Além disso, também suporta algumas outras flags
-V: Apenas imprime a versão e sai-json: Exibe no formato json-c=n: Exibe o número especificado de linhas de conflito no contexto (parece não ter nenhum efeito)
Também há alguns analisadores externos, como shadows, que é responsável por detectar problemas de ocultação de variáveis com nomes curtos. Como é externo, precisa ser baixado usando go install
$ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latestO formato de uso é o seguinte
$ go vet -vettool=$(which shadow)test
$ go test -h
usage: go test [build/test flags] [packages] [build/test flags & test binary flags]
Run 'go help test' and 'go help testflag' for details.O comando test é o comando da cadeia de ferramentas da linguagem Go que fornece funcionalidade de teste. Esta função é muito importante. Para um software, testes completos são indispensáveis. Aqui apenas introduziremos brevemente como usar o comando test. Se quiser saber mais sobre testes, visite: 测试
Além de suportar os parâmetros de compilação do comando build, o test também suporta os seguintes parâmetros
-args: Parâmetros de entrada do programa-c: Compila o arquivo binário de teste do pacote atual para o diretório atual, mas não executa, nomeando comopkg.test-exec: Executa alguns outros comandos antes do início do teste-json: O estilo de saída do teste se torna json-o: Especifica o caminho do arquivo binário de teste
Também suporta muitas testflag. Use o comando help para visualizar todas as testflag
$ go help testflag
`go test` 命令既接受作用于 `go test` 本身的标志,
也接受作用于生成的测试二进制文件的标志。
`go test` 命令识别以下标志,并用于控制任何测试的执行:
-bench regexp
-benchtime t
-count n
......Apresentamos alguns comumente usados
-v: Exibe os resultados de teste de cada caso de uso.-timeout duration: Tempo limite de execução do teste-skip regexp: Pula os casos de teste especificados-short: Faz com que casos de teste que levam muito tempo sejam executados de forma mais curta-shuffle: Embaralha a ordem de execução de todos os casos de teste-run regexp: Executa os casos de teste especificados-list regexp: Lista cada caso de teste-cpu 1,2,4: Especifica o número de CPUs-count n: Especifica quantas vezes cada caso de teste deve ser executado
O uso mais simples é sem parâmetros, que executará todos os casos de teste no pacote atual e exibirá os resultados.
$ ls *_test.go
hello_test.go
$ go test
PASS
ok golearn 0.522sEspecificar um arquivo de teste
$ go test hello_test.go
ok command-line-arguments 0.041sAdicionar o parâmetro -v permite visualizar saída mais detalhada, o que é muito comum.
$ go test -v hello_test.go
=== RUN TestHello
hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok command-line-arguments 0.041sEspecificar um caso de teste
$ go test -v -run TestHello
=== RUN TestHello
hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok golearn 0.028sDurante o teste, o comando test tem dois modos. Primeiro, vamos falar sobre o modo de diretório. Quando o comando test é executado sem o parâmetro package, ele executará o teste no modo de diretório, como os seguintes comandos
$ go test
$ go test -vNeste modo, o cache de teste é desabilitado. O outro modo é o modo de lista. Quando o parâmetro package não está vazio, o teste será executado no modo de lista. A diferença entre ele e o anterior é se o cache de teste está habilitado. Por exemplo
$ go test -v .
$ go test -v ./...
$ go test .
$ go test -v net/httpNo modo de lista, o Go compilará os arquivos de teste de cada pacote no pacote especificado em arquivos binários e os executará. Para evitar executar testes repetidamente, o Go armazenará os resultados em cache por padrão e não recompilará na segunda execução. O cache será habilitado por padrão ao usar os seguintes parâmetros
-benchtime-cpu-list-parallel-runshort-timeout-failfast-v
Usar outros parâmetros além destes pode desabilitar o cache. O método recomendado oficialmente é usar -count=1 para desabilitar o cache. Por exemplo
$ go test -v -count=1 ./...Diretivas
Diferentemente dos comandos, as diretivas do Go existem no código-fonte de forma hard-coded. Elas têm outro nome mais técnico: diretivas de pragma (pragma directives).
Compiladores e linkers mudarão seu comportamento devido a elas, alcançando assim o controle de compilação, um pouco como macros em linguagem C. Claro, nem todas as diretivas são usadas para influenciar a compilação. Algumas são usadas para outros comportamentos funcionais. Por exemplo, a diretiva generate é geralmente usada para funcionalidade de geração de código. Essas diretivas geralmente existem na forma de comentários e têm //go: como prefixo, sem nenhum espaço no meio, como a diretiva //go:generate. Todos os tipos de diretivas são divididos em dois tipos
- Diretivas funcionais: Estas são diretivas funcionais fornecidas pelo Go que podem ser usadas livremente, como
generate,embed,build. - Diretivas de compilador: Estas diretivas precisam ser usadas com cuidado. Uso indevido pode levar a resultados imprevisíveis.
Exceto pelas diretivas funcionais, a maioria das diretivas só pode atuar em assinaturas de função. Para diretivas de compilador, execute o comando go doc compile para visualizar suas diretivas. Para todas as diretivas, você pode encontrar informações sobre elas em cmd/compile/internal/ir/node.go: 440.
generate
$ go help generate
usage: go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]A diretiva generate, como o nome sugere, está relacionada à geração. Geralmente, sua função é executar comandos que geram código e atualizam código-fonte, mas na verdade pode executar qualquer comando. Além disso, diferentemente de outras diretivas, generate tem um comando dedicado que pode executar todas as diretivas generate localizadas em arquivos de código-fonte. Pode usar nomes de arquivos ou nomes de pacotes como parâmetros de entrada para indicar em quais arquivos executar as diretivas generate. Aqui estão seus outros parâmetros.
-run=regex: Executa as diretivas generate especificadas-skip=regex: Pula as diretivas generate especificadas-n: Imprime os comandos que serão executados-x: Imprime os comandos executados durante o processo-v: Exibe os arquivos processados
Além disso, os comandos executados na diretiva generate também suportam os seguintes parâmetros embutidos
$GOARCH: Arquitetura da CPU$GOOS: Sistema operacional$GOFILE: Nome do arquivo$GOLINE: Número da linha$GOPACKAGE: Nome do pacote$GOROOT: Go root$DOLLAR: Símbolo de dólar$PATH: Variável de ambiente path
Veja um exemplo: sem código, apenas um comentário
package main
//go:generate echo "hello world!"Executar comando
$ go generate .
hello world!Este exemplo executa um comando go
package main
//go:generate go versionExecutar comando
$ go generate .
go version go1.21.3 windows/amd64A diretiva generate pode ser usada para executar qualquer comando, como swagger para gerar documentação de API, ou Wire para gerar código IOC. No entanto, esta diretiva não é adequada para executar comandos muito complexos. É adequada para executar comandos curtos. Se houver requisitos complexos, pode-se usar scripts ou makefile como substituto.
embed
A diretiva embed foi adicionada na versão 1.16. Sua função é empacotar arquivos estáticos junto com o arquivo binário, como templates HTML, por exemplo. Seu formato é o seguinte
//go:embed patternpattern pode ser uma expressão glob, um diretório ou um arquivo específico. Veja um exemplo
package main
import "embed"
//go:embed *
var static embed.FSA diretiva embed requer que esteja localizada acima de uma variável global do tipo embed.FS. Note que deve ser uma variável global, e é necessário importar o pacote embed para usá-la. Neste exemplo, * representa que todos os arquivos no diretório atual serão empacotados no arquivo binário, mas não permitirá diretórios que começam com ..
O exemplo a seguir mostra como ler conteúdo de arquivos embutidos
package main
import (
"embed"
"fmt"
)
//go:embed *.txt
var static embed.FS
func main() {
bytes, err := static.ReadFile("hello.txt")
if err != nil {
panic(err)
}
fmt.Println(string(bytes))
}Possui apenas três métodos, e o uso não é diferente de um sistema de arquivos comum. Além disso, como implementa a interface io/Fs, também pode ser passado como um objeto Fs.
func (f FS) Open(name string) (fs.File, error)
func (f FS) ReadFile(name string) ([]byte, error)
func (f FS) ReadDir(name string) ([]fs.DirEntry, error)O exemplo a seguir mostra como embutir um arquivo html através da diretiva embed e acessá-lo através de um serviço http.
package main
import (
"embed"
"net/http"
)
//go:embed index.html
var htmlFs embed.FS
func main() {
http.Handle("/", http.FileServer(http.FS(htmlFs)))
http.ListenAndServe(":8080", http.DefaultServeMux)
}O resultado do acesso é o seguinte
$ curl -s -GET 127.0.0.1:8080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world!</title>
</head>
<body>
<H1>Hello World!</H1>
<script>
alert("hello world!");
</script>
</body>
</html>A diretiva embed também suporta que o tipo da variável global seja []byte. Veja o exemplo a seguir
package main
import (
_ "embed"
"net/http"
)
//go:embed index.html
var rawdata []byte
func main() {
http.HandleFunc("/", func(writer http.ResponseWriter, request *http.Request) {
writer.Write(rawdata)
})
http.ListenAndServe(":8080", http.DefaultServeMux)
}O efeito implementado é semelhante ao exemplo anterior.
$ curl -s -GET 127.0.0.1:8080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world!</title>
</head>
<body>
<H1>Hello World!</H1>
<script>
alert("hello world!");
</script>
</body>
</html>build
Na seção build-Controle de Compilação, falamos sobre como usar a diretiva // +build para controlar o comportamento de compilação. A diretiva //go:build foi lançada na versão 1.17, com a intenção de substituir a diretiva anterior, mas agora na versão 1.21 ainda não foi substituída. Estima-se que existirá de forma coexistente no futuro. Sobre esta nova diretiva, a documentação oficial também tem uma introdução: build constraints. Sua função não é muito diferente da anterior, mas a sintaxe é mais rigorosa e suporta expressões booleanas. Veja um exemplo
//go:build (linux && 386) || (darwin && !cgo)
package pkg_nameEsta maneira tem legibilidade muito maior do que a anterior.
line
A diretiva line afetará o número da linha, número da coluna e nome do arquivo da próxima linha. Sua função se limita a isso, e na maioria das vezes pode ser usada para depurar erros, por exemplo. Ao ocorrer um erro, mudará as informações de saída do compilador.
package main
var a undefinedType
func main() {
}Normalmente, o compilador exibirá
.\main.go:3:7: undefined: undefinedTypeMas se usar a diretiva line, será diferente
package main
//line abc.go:10:100
var a undefinedType
func main() {
}Então sua saída será
abc.go:10:106: undefined: undefinedTypeE devido a razões históricas, a diretiva line é a única diretiva com uso diferente das outras. Seu formato é
//line filename:line:columnComo você pode ver, não requer go: como prefixo.
linkname
Esta operação de diretiva pode ser usada para linkar funções ou variáveis globais de outros pacotes, mesmo que sejam tipos privados. Esta operação frequentemente aparece na biblioteca padrão, especialmente em runtime. Algumas funções sem corpo são implementadas através desta maneira, e outra parte das funções com corpo vazio é implementada por assembly. Vamos ver seu uso. O formato de uso é o seguinte
//go:linkname nome_do_tipo_linkado tipo_linkadoE antes de usar, por exemplo, importe o pacote unsafe. Veja um exemplo simples de linkar um tipo privado na biblioteca padrão
import (
"fmt"
"unsafe"
)
//go:linkname memhash runtime.memhash
func memhash(p unsafe.Pointer, h, s uintptr) uintptr
func MemHash(data []byte) uint64 {
ptr := unsafe.Pointer(unsafe.SliceData(data))
return uint64(memhash(ptr, 0, uintptr(len(data))))
}
func main() {
fmt.Println(MemHash([]byte("hello")))
}Saída
15395306441938000233Ela linkou a função privada runtime.memhash com a função que declaramos. Esta função não tem corpo, apenas uma assinatura, servindo apenas como um veículo. A função memhash serve para calcular o valor hash com base na memória, dado um ponteiro, semente de hash e offset de memória. Este processo de link é concluído durante o período de compilação.
Se não for da biblioteca padrão, a situação é um pouco diferente. Por exemplo, há uma função test no pacote example. Antes de linkar, é necessário importar anonimamente este pacote.
package example
// Um tipo privado, inacessível do exterior.
func test() string {
return "a"
}package main
import (
"fmt"
_ "golearn/example"
_ "unsafe"
)
//go:linkname test golearn/example.test
func test() string
func main() {
fmt.Println(test())
}Saída
aComo você pode ver, o link foi bem-sucedido. Este método pode contornar o sistema de módulos do Go e fazer o que quiser, mas não é recomendado usar em larga escala, a menos que você saiba o que está fazendo.
noinline
A diretiva noinline indica que uma função é proibida de otimização de inline, mesmo que seja muito simples. Veja um exemplo simples
package main
func val() string {
return "val"
}
func main() {
var c = val()
_ = c
}val é uma função muito simples que retorna um literal de string. Como é muito simples e o resultado é sempre previsível, durante a compilação será otimizada pelo compilador para a seguinte forma
package main
func main() {
var c = "val"
_ = c
}Vamos ver como é em assembly. Como você pode ver, não há chamada para a função val.
TEXT main.val(SB), NOSPLIT|NOFRAME|ABIInternal, $0-0
FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
LEAQ go:string."val"(SB), AX
MOVL $3, BX
FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
RETAgora adicione a diretiva noinline
package main
//go:noinline
func val() string {
return "val"
}
func main() {
var c = val()
_ = c
}Vamos ver sua forma de assembly
CMPQ SP, 16(R14)
PCDATA $0, $-2
JLS 17
PCDATA $0, $-1
PUSHQ BP
MOVQ SP, BP
FUNCDATA $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
FUNCDATA $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
PCDATA $1, $0
CALL main.val(SB)
POPQ BP
RETDesta vez, você pode ver muito claramente a chamada main.val, e esta é exatamente a função da diretiva noinline: impedir o inline de função durante a otimização do compilador.
nosplit
A diretiva nosplit serve para pular a detecção de estouro de pilha. Como o modelo de agendamento concorrente do Go é um agendamento preemptivo, se uma função executar código de nível muito baixo e outras goroutines não forem adequadas para serem preemptadas ao chamar esta função, pode-se usar esta diretiva para indicar.
//go:nosplit
func nospilitFn()Após usar esta diretiva, não haverá mais crescimento de pilha.
noescape
noescape, como o nome sugere facilmente, está relacionado a escape. Sua função é indicar que a função atual não terá comportamento de escape de memória. Após a execução, todos os recursos serão recuperados, e esta função deve ter apenas assinatura sem corpo. Neste caso, geralmente a implementação da função é feita em assembly.
Por exemplo, memhash usado anteriormente usará esta diretiva
//go:noescape
//go:linkname memhash runtime.memhash
func memhash(p unsafe.Pointer, h, s uintptr) uintptrDesta forma, o compilador não realizará análise de escape nela. A premissa é que você deve garantir que não ocorra escape. Se ocorrer, não se sabe quais serão as consequências.
uintptrescapes
A diretiva uintptrescapes indica que o parâmetro do tipo uintptr nesta função foi convertido para um valor de ponteiro e escapou para o heap, e deve ser mantido vivo. Esta diretiva é geralmente usada para algumas chamadas de sistema de baixo nível. Na maioria dos casos, não é necessário entendê-la.
//go:uintptrescapes
func nospilit(ptr uintptr) uintptrAnteriormente, deveria haver uma diretiva notinheaps usada para indicar que um tipo não permite alocação de memória no heap, mas não se sabe em qual versão foi removida.
norace
A diretiva norace indica que o acesso à memória de uma função não requer mais análise de corrida. Geralmente é usada ao executar código de baixo nível onde não é adequado realizar análise de corrida.
//go:norace
func low_level_code(ptr uintptr) uintptrTIP
Algumas diretivas são limitadas para uso apenas pelo pacote runtime, e não podem ser usadas externamente. Elas envolverão coisas mais profundas. Se quiser entender, você pode ver informações sobre elas em Runtime-only compiler directives.
