Riga di Comando

I comandi in Go includono un'intera suite di toolchain che copre documentazione, formattazione, ispezione del codice, compilazione, test, gestione delle dipendenze e molti altri aspetti dello sviluppo Go.
bug Segnala un bug
build Compila pacchetti e dipendenze
clean Rimuovi file oggetto
doc Mostra documentazione nel codice sorgente
env Visualizza informazioni sulle variabili d'ambiente Go
fix Risolvi problemi di compatibilità API dovuti a cambiamenti di versione go
fmt Formatta il codice sorgente
generate Genera codice
get Aggiungi dipendenze
install Installa e compila pacchetti
list Elenca pacchetti/moduli
mod Comandi per la manutenzione dei moduli
work Comandi per la manutenzione dell'area di lavoro
run Compila ed esegui
test Esegui test
tool Esegui uno strumento go specifico
version Mostra informazioni sulla versione di go
vet Scansiona e segnala possibili problemi nel codice sorgenteQuesto articolo descrive semplicemente il loro utilizzo. Tutti i contenuti fanno riferimento alla documentazione ufficiale. Per ulteriori dettagli, visita cmd/go.
help
Il primo comando da conoscere è help, che permette di leggere l'utilizzo dei comandi. Ci sono due modi d'uso: per ottenere informazioni brevi sull'utilizzo, aggiungi il flag -h dopo il comando specificato, ad esempio
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.go mostrerà brevemente l'utilizzo del comando e suggerisce di usare il comando help per informazioni più dettagliate
$ 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'.Utilizza saggiamente il comando help per ottenere molte informazioni sui comandi.
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 exportedIl comando doc produce documentazione per pacchetti specificati, costanti, funzioni, tipi, variabili, metodi e persino campi di struct. Senza argomenti, produce i commenti del pacchetto corrente
$ go docPuoi anche specificare un pacchetto da visualizzare, ad esempio la documentazione del pacchetto 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.
......O un tipo specifico
$ 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.
...O una funzione specifica
$ 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.Ha i seguenti flag comuni
-u: visualizza tipi privati-all: visualizza tutta la documentazione di un pacchetto specificato-short: solo una breve descrizione su una riga-src: produce il codice sorgente-cmd: produce anche la documentazione del codice per pacchetti che appartengono ai comandi go.
Ad esempio, per visualizzare la variabile runtime.inf, che non è esposta pubblicamente
$ go doc -u runtime.inf
package runtime // import "runtime"
var inf = float64frombits(0x7FF0000000000000)Utilizzare bene il comando doc per leggere la documentazione in modo più conveniente.
Un altro modo per leggere la documentazione dei comandi è esaminare il codice sorgente, poiché alcuni comandi non hanno documentazione così dettagliata, mentre nel codice sorgente ci sono spiegazioni più approfondite. Poiché questi comandi sono scritti interamente in go, sono facili da leggere. Questi comandi si trovano nel pacchetto src/cmd, ogni sottopacchetto è un comando separato, il punto di ingresso si trova nel file 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,
}
}Qui troverai tutti i sottocomandi di go e le relative informazioni di aiuto.
bug
$ go help bug
usage: go bug
Bug opens the default browser and starts a new bug report.
The report includes useful system information.Questo comando non ha parametri o flag. Apre il browser predefinito per accedere alla pagina issue del repository github.com/golang/go, facilitando la segnalazione di bug. Non ha altre funzioni.
version
Il comando version mostra le informazioni sulla versione corrente di go.
$ go version -h
usage: go version [-m] [-v] [file ...]Senza parametri, mostra la versione corrente del linguaggio go
$ go version
go version go1.21.0 windows/amd64Accetta anche percorsi di file come parametri e mostrerà la versione di go utilizzata per compilare tutti i file binari eseguibili riconoscibili in quel percorso.
$ 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.0Il parametro -v specifica al comando version di provare a produrre la versione go di file non riconoscibili, il parametro -m produce le informazioni sul modulo del file binario e alcuni parametri di compilazione. Ecco un esempio semplice.
$ 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=v1go stesso è un file binario. In realtà, senza parametri, go version produce la versione del linguaggio go del proprio file binario, poiché tutta la toolchain di cmd/go è implementata dal linguaggio go stesso.
env
Il comando env permette di visualizzare tutte le variabili d'ambiente go. La modifica di queste variabili d'ambiente influenzerà il comportamento della toolchain go.
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.Eseguendo questo comando senza parametri, vengono prodotti i valori di tutte le variabili d'ambiente go
$ go env
set GO111MODULE=on
set GOARCH=amd64
...Passando il nome di una variabile d'ambiente come parametro, si può produrre solo il valore di quella variabile
$ go env GO111MODULE
onAggiungendo -json si produce il formato JSON
$ go env -json
{
"AR": "ar",
"CC": "gcc",
......
}Usando il flag -w e passando un parametro nella forma var=value, si modifica permanentemente il valore di una variabile
$ go env -w GO111MODULE=onUsando il flag -u, si può ripristinare una variabile al valore predefinito
$ go env -u GO111MODULEEseguendo go help environment si può visualizzare la descrizione di ogni variabile d'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.
......Di seguito sono presentate alcune variabili d'ambiente comunemente utilizzate
GOVERSION
Il valore di questa variabile d'ambiente dipende dalla versione del linguaggio go, e il numero di versione proviene dal file $GOROOT/VERSION, che registra la versione corrente di go e il tempo di compilazione.
$ cat $GOROOT/VERSION
go1.21.3
time 2023-10-09T17:04:35ZIl valore della variabile runtime.Version è lo stesso di GOVERSION e questa variabile d'ambiente non può essere modificata.
GOENV
Nella directory $GOROOT c'è un file di configurazione predefinito chiamato 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=autoIl formato è semplicemente key=value. I valori delle variabili d'ambiente modificati con il comando go env -w key=value vengono scritti nel file di configurazione. Tuttavia, è possibile non utilizzare il file di configurazione predefinito. La variabile d'ambiente GOENV può specificare manualmente l'indirizzo del file di configurazione env, e il valore della variabile d'ambiente GOENV può essere sovrascritto solo dalle variabili d'ambiente del sistema operativo e non può essere modificato dal comando go env -w.
GOHOSTARCH
Rappresenta l'architettura CPU della macchina locale. Serve solo per visualizzazione. Il valore di questa variabile d'ambiente non viene letto dal file di configurazione e non può essere modificato.
GOHOSTOS
Rappresenta il sistema operativo della macchina locale. Serve solo per visualizzazione. Il valore di questa variabile d'ambiente non viene letto dal file di configurazione e non può essere modificato.
GOOS
Durante la compilazione, il valore di GOOS determina in quale file binario del sistema di destinazione verrà compilato il codice sorgente. Il valore predefinito è GOHOSTOS, ovvero il sistema operativo locale. Ha le seguenti opzioni
linuxdarwinwindowsnetbsdaixandroid
I sistemi operativi effettivamente supportati non si limitano a questi. Usa il comando go tool dist list per visualizzare tutti i valori supportati
$ 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 la compilazione, il valore di GOARCH determina quale architettura CPU verrà utilizzata durante la compilazione. Il valore predefinito è GOHOSTARCH, ovvero l'architettura CPU locale. Ha le seguenti opzioni
amd64386armppc64
Le architetture effettivamente supportate non si limitano a queste. Usa il comando go tool dist list per visualizzare tutti i valori supportati
$ go tool dist list | awk -F '/' '{print $2}' | awk '!seen[$0]++'
ppc64
386
amd64
arm
arm64
riscv64
wasm
loong64
mips
mips64
mips64le
mipsle
ppc64le
s390xVa notato che GOOS e GOARCH non possono essere combinati arbitrariamente. Alcuni sistemi operativi supportano solo architetture CPU specifiche.
GOROOT
GOROOT rappresenta la directory radice dell'installazione del linguaggio go. Il valore di GOROOT non può essere modificato direttamente e può essere sovrascritto solo dalle variabili d'ambiente del sistema operativo.
$ ls $GOROOT -1
api
bin
codereview.cfg
CONTRIBUTING.md
doc
go.env
lib
LICENSE
misc
PATENTS
pkg
README.md
SECURITY.md
src
test
VERSIONNella directory radice ci sono diverse cartelle o file importanti
lib, contiene alcune dipendenze. Attualmente c'è solo una libreria con informazioni sul fuso orario di vari paesi del mondo, situata in$GOROOT/lib/time. I file binari compilati non conterranno queste informazioni sul fuso orario.pkg, contiene alcune librerie di strumenti e file di intestazione. Ad esempio, il comandogo toolcercherà i file binari della toolchain go nella directory$GOROOT/pkg/toolbin, contiene file binari. Per impostazione predefinita, ci sono solo due file eseguibili:goegofmt.$GOROOT/bindovrebbe essere aggiunto alle variabili di sistema, altrimenti non sarà possibile utilizzare i comandi go.src, contiene il codice sorgente goVERSION, questo file contiene le informazioni sulla versione del linguaggio gogo.env, questo file è il file di configurazioneenvpredefinito
GOPATH
Il valore predefinito di GOPATH è $HOME/go. Il valore di questa variabile d'ambiente specifica dove cercare i file importati durante l'analisi delle istruzioni import. Nei primi tempi, prima di gomod, GOPATH era utilizzato specificamente per memorizzare varie librerie di terze parti. La sua struttura è la seguente
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)Dopo la nascita di gomod, GOPATH è diventato semplicemente un luogo per memorizzare le dipendenze scaricate con go get e i file binari scaricati e compilati con go install. Va notato che la posizione di GOPATH non può essere la stessa di GOROOT, altrimenti non avrà alcun effetto.
$ go env GOBIN
warning: GOPATH set to GOROOT (/home/user/go) has no effectAl momento della stesura di questo articolo, la versione del linguaggio go è arrivata a go1.21.3. Oltre a progetti molto antichi, quasi nessuno usa più gopath per gestire le dipendenze.
GOBIN
GOBIN è utilizzato per memorizzare i file binari eseguibili di terze parti scaricati e compilati con go install. Il suo valore predefinito è $GOPATH/bin. Come $GOROOT/bin, questa directory dovrebbe essere aggiunta alle variabili d'ambiente del sistema operativo, altrimenti non sarà possibile utilizzare i file binari nella directory GOBIN.
GOMODCACHE
GOMODCACHE indica la posizione in cui vengono memorizzate le dipendenze scaricate con go get. Il valore predefinito è $GOPATH/pkg/mod. Il formato di memorizzazione è il seguente
$GOMODCACHE/domain/username/project@verionNella stessa directory ci sarà anche una cartella chiamata sumdb, utilizzata per memorizzare le informazioni relative al database di checksum delle dipendenze.
GOCACHE
Memorizza le informazioni di cache per la compilazione. Il suo valore predefinito è $HOME/.cache/go-build. In questa directory verrà generato un file README.
$ 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.Ogni build genera molti file. go memorizza questi file per riutilizzarli durante la compilazione successiva.
GOTEMPDIR
Utilizzato per i file temporanei generati durante la compilazione, ad esempio i file binari temporanei da eseguire con go run. Il suo valore predefinito è la directory temporaria specificata dal sistema operativo: /tmp su mac o linux, %TEMP% su windows. Può anche essere modificato in una posizione specificata dall'utente.
GO111MODULE
Questa variabile d'ambiente indica quale metodo utilizzare per gestire le dipendenze del progetto go. Ha tre valori disponibili
off: disattiva gomod, utilizza gopath e ignora tutti i filego.modon: utilizza gomod, non utilizza gopath (predefinito).auto: rilevamento automatico. Se il file del progetto contienego.mod, utilizza gomod per la gestione
TIP
Perché si chiama GO111MODULE e non semplicemente GOMODULE? Perché gomod è stato introdotto per la prima volta nella versione go1.11.
GOPROXY
Proxy del modulo go. Il valore predefinito è https://proxy.golang.org,direct. L'URL è separato da virgole. direct significa utilizzare direttamente VCS per saltare il proxy del modulo. Viene eseguito solo quando il primo non è accessibile. C'è anche un'opzione disponibile: off, che indica di proibire il download di qualsiasi modulo. Inoltre, GOPROXY può anche essere un indirizzo di file, ad esempio
GOPROXY=file://$(go env GOMODCACHE)/cache/downloadUsando go get -x puoi vedere i comandi eseguiti durante il processo di download delle dipendenze e sapere se sta utilizzando il 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.1L'utilizzo di un proxy del modulo può migliorare efficacemente la velocità di download del modulo. Per gli utenti in Cina, fondamentalmente senza un proxy non è possibile accedere al proxy ufficiale predefinito. Attualmente, i proxy di moduli di terze parti pubblici e affidabili sono i seguenti
https://proxy.golang.com.cn, open source e fornisce anche servizi enterprisehttps://goproxy.cn, fornito e open source da Qiniu Cloud
C'è anche una soluzione open source per creare autonomamente un proxy di moduli: goproxy
GOSUMDB
GOSUMDB è utilizzato per impostare l'indirizzo del database di rilevamento del checksum della libreria di dipendenze. Il predefinito è sum.golang.org. Quando imposti un proxy, go accederà al database di checksum tramite il proxy.
GOPRIVATE
La variabile d'ambiente GOPRIVATE è utilizzata per impostare le librerie private. Le librerie corrispondenti non verranno verificate tramite sumdb e non passeranno attraverso il proxy. Verranno scaricate direttamente tramite VCS. Supporta impostazioni con caratteri jolly, separati da virgole. Come mostrato di seguito, tutte le dipendenze con suffisso corp.example.com e chiamate github.com/gohper/myproject non passeranno attraverso il proxy e sumdb.
GOPRIVATE=*.corp.example.com,github.com/gohper/myprojectPuoi anche impostare direttamente un utente o un'organizzazione specifica
GOPRIVATE=github.com/gopher,github.com/myorganizationGONOPROXY
Indica quali dipendenze non devono passare attraverso il proxy. Le regole sono le stesse di GOPRIVATE e sovrascrivono GOPRIVATE.
GONOSUMDB
Indica quali dipendenze non devono passare attraverso il database di checksum. Le regole sono le stesse di GOPRIVATE e sovrascrivono GOPRIVATE.
GOINSECURE
Indica quali dipendenze devono essere scaricate direttamente tramite VCS. Le regole sono le stesse di GOPRIVATE e vengono sovrascritte da GONOPROXY e GONOSUMDB.
GOVCS
Imposta il sistema di controllo versione per la gestione dei moduli. Il predefinito è public:git|hg,private:all. Puoi anche limitare VCS per domini specifici, ad esempio
GOVCS=github.com:git,evil.com:off,*:git|hgNella restrizione sopra, github può usare solo git, evil.com non è consentito e | può rappresentare più VCS. Se non si desidera applicare alcuna restrizione, è possibile impostare come segue
GOVCS=*:allSe non si consente l'uso di alcun VCS, è possibile impostare come segue
GOVCS=*:offGOWORK
Imposta se abilitare l'area di lavoro. Il predefinito è vuoto, cioè abilitato. Se impostato su off, non verrà abilitato e tutti i file go.work verranno ignorati.
GOTOOLDIR
Imposta la posizione della toolchain go da utilizzare. Il predefinito è $GOROOT/pkg/tool, dove si trova anche la toolchain predefinita.
GODEBUG
Imposta le opzioni di debug, controlla il comportamento di esecuzione di alcuni programmi go sotto forma di coppie chiave-valore, ad esempio
GODEBUG=http2client=0,http2server=0Queste impostazioni sono convenienti quando si verificano cambiamenti incompatibili durante l'aggiornamento della versione, consentendo a go di tornare al comportamento precedente. Ad esempio, in 1.21 non è più consentita la situazione panic(nil). Per questo motivo, il team ufficiale di go ha registrato specificamente GODEBUG History. Visita GODEBUG per ulteriori dettagli.
CGO_ENABLED
Indica se abilitare cgo. Il predefinito è 1, cioè abilitato. Impostando su 0 si disattiva.
Le variabili d'ambiente sopra menzionate sono quelle più comunemente utilizzate. Per quelle meno comuni, come CGO, WASM, ecc., non verranno fornite ulteriori introduzioni. Se interessati, è possibile informarsi autonomamente.
build
Go supporta due tipi di compilatori: gccgo e gc. gcc è un vecchio compilatore C/C++ che supporta più linguaggi, incluso go. gc non significa garbage collector, ma go compiler. Il linguaggio go ha completato il bootstrap in go1.5. gc è un compilatore scritto completamente in linguaggio go e il suo codice sorgente si trova nel pacchetto cmd/compile. Poiché è completamente implementato in linguaggio go, è molto conveniente per comprendere e apprendere i suoi meccanismi interni. Per inciso, anche il debugger del linguaggio go è disponibile in due versioni: gdb e dlv. Il primo è un vecchio debugger C/C++ che supporta più linguaggi, incluso go. Il secondo è un debugger scritto in linguaggio go che offre un supporto più amichevole per il linguaggio go. Anche questo è open source e si consiglia di utilizzare quest'ultimo.
Il comando build viene utilizzato per compilare i file sorgente go in file binari eseguibili. Sperimentarai un'esperienza di compilazione estremamente rapida, che è una delle caratteristiche del linguaggio go.
$ go build -h
usage: go build [-o output] [build flags] [packages]
Run 'go help build' for details.Accetta tre parametri: uno è il percorso di output del file indicato dal flag -o, uno è il flag di compilazione build flags utilizzato per definire il comportamento di compilazione e l'ultimo è il pacchetto da compilare. Questo parametro deve essere posizionato per ultimo. Ecco un esempio semplice che non utilizza flag di compilazione.
# Windows
$ go build -o .\bin\golearn.exe golearn
# macOS / Linux
$ go build -o ./bin/golearn golearn./bin/golearn.exe indica il percorso di output e golearn indica il modulo da compilare. Può anche essere un file di ingresso o una cartella. Ad esempio, il semplice esempio seguente utilizza main.go come file di ingresso per la compilazione.
# Windows
$ go build -o .\bin\golearn.exe main.go
# macOS / Linux
$ go build -o ./bin/golearn main.goDurante la compilazione, ignorerà tutti i file che terminano con _test.go, poiché per convenzione questi sono file di test.
Inoltre, il comando build supporta numerosi flag di compilazione per controllare alcuni comportamenti durante la compilazione.
-x: produce istruzioni dettagliate durante il processo di compilazione-n: simile a-x, ma la differenza è che produce solo queste istruzioni senza eseguirle effettivamente.-v: produce i pacchetti compilati-p: numero di processi concorrenti durante il processo di compilazione-a: forza la ricompilazione, anche se è già aggiornata.-compiler: specifica quale compilatore utilizzare,gccgoogc. Quest'ultimo è un compilatore scritto in go.-race: abilita il rilevamento delle race condition-msan: abilita l'analisi della memoria-asan: abilita l'analisi dell'indirizzo-cover: abilita il rilevamento della copertura del codice-buildmode: specifica la modalità di compilazione. Le opzioni sonoarchive,c-archive,c-shared,default,shared,exe,pie,plugin.-pgo: specifica il file pgo-trimpath: elimina il prefisso del percorso del file sorgente. Ad esempio, il percorso relativo/var/lib/go/src/main.godopo l'eliminazione avrà solo il percorso relativo al percorso del modulo/main.goquando ottenuto tramiteruntimedurante l'esecuzione. Abilitando questa opzione, il tempo di compilazione aumenterà significativamente, circa del 20-40%, a seconda del numero di file.-toolexec: alcuni comandi go da eseguire prima della compilazione, nel formato-toolexec 'cmd args'.-gcflags: specifica alcuni tag per il compilatore gc-gccgoflags: specifica alcuni tag per il compilatore gccgo-ldflags: specifica alcuni tag per lo strumento di link
Per alcuni parametri di passaggio come ldflags, è possibile passare parametri come "-help" per ottenere i possibili valori. Ad esempio
$ 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
......Quelli sopra menzionati sono i più comunemente utilizzati. Per altri meno comuni, è possibile informarsi autonomamente.
gcflags
Tramite gcflags è possibile passare alcuni parametri al compilatore gc per controllare comportamenti specifici. Il formato di utilizzo è -gcflags="pattern=args list", dove args list è l'elenco dei parametri e pattern è l'ambito di applicazione. Ci sono i seguenti valori disponibili
main, il percorso del pacchetto di primo livello in cui si trova il file di ingressoall, il modulo corrente e tutte le sue dipendenze nella modalità correntestd, libreria standardcmd, tutti i file sorgente nel pacchettocmd- Caratteri jolly, come
.,./...,cmd/....
La regola pattern si applica a tutti i flag che supportano questo formato, come ldflags. È possibile visualizzare i valori disponibili dei parametri con il seguente comando
$ go build -gcflags -help
usage: compile [options] file.go...
-% debug non-static initializer
-+ compile runtime
-B disable bounds checking
-C disable printing of column number 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 errors affected by //line directives
-N disable optimizations
-S print assembly listing
-V print version and exit
-W debug parse tree after typechecking
......Di seguito sono presentati alcuni parametri comunemente utilizzati
-S: produce la forma assembly del codice-N: disattiva l'ottimizzazione della compilazione-m: produce le decisioni di ottimizzazione-l: disattiva l'inlining delle funzioni-c: numero di processi concorrenti per la compilazione-dwarf: genera flag DWARF
Ad esempio, se si desidera visualizzare la forma assembly del codice, è possibile utilizzare il parametro -S e disattivare l'ottimizzazione e l'inlining per ripristinare la sua forma originale. Come 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
Tramite ldflags è possibile passare alcuni parametri al linker per controllare comportamenti specifici. È possibile visualizzare tutti i valori disponibili di ldflags con il seguente comando, che sono circa una ventina.
$ 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)
.....Il parametro -X di ldflags è una funzione molto pratica. Permette di definire il valore di variabili stringa di pacchetti specificati durante il linking. Grazie a questa funzione, possiamo iniettare comodamente alcune metainformazioni durante la compilazione. Ed è solo una variabile, quindi è anche comodo da ottenere durante l'esecuzione. Ecco un esempio semplice.
package main
import "fmt"
var (
Version string
)
func main() {
fmt.Println(Version)
}Esegui il comando
go build -ldflags "-X main.Version=$(git describe --always)" main.goDopo l'esecuzione, verrà prodotto il checksum sha1 del commit git.
5e3fd7aAltri parametri pratici includono
-w: non genera DWARF, che è un'informazione conveniente per il debug del codice sorgente.-s: disattiva la tabella dei simboli
Questi due vengono solitamente utilizzati insieme e possono ridurre significativamente le dimensioni del file binario compilato, circa del 40%-50%. Lo svantaggio è anche evidente: non è possibile eseguire il debug. Ecco un esempio.
$ go build -ldflags="-w -s" main.goCompilazione incrociata
La compilazione del linguaggio go ha due caratteristiche principali: la prima è la velocità, l'altra è la compilazione incrociata. La compilazione incrociata si riferisce alla possibilità di compilare localmente il codice obiettivo di altri sistemi, ad esempio compilare file binari per linux o darwin su windows, e viceversa. Molti linguaggi supportano la compilazione incrociata, il che non è nulla di straordinario, ma la compilazione incrociata del linguaggio go è molto semplice, richiede solo i seguenti passaggi
- Imposta la variabile d'ambiente GOOS per selezionare il sistema operativo di destinazione
- Imposta la variabile d'ambiente GOARCH per selezionare l'architettura CPU di destinazione
- Utilizza
go buildper compilare come al solito
L'intero processo è molto breve, non richiede strumenti o configurazioni aggiuntive e la velocità è veloce come al solito. Come mostrato di seguito
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_winIl primo passaggio SET CGO_ENABLED=0 disabilita cgo. Una volta che il tuo codice utilizza cgo, non è possibile utilizzare normalmente la compilazione incrociata. Il secondo passaggio SET GOOS imposta il sistema di destinazione. Le opzioni sono linux, darwin, windwos, netbsd. Il terzo passaggio imposta l'architettura CPU, SET GOARCH. Le opzioni sono amd64, 386, arm, ppc64. L'ultimo passaggio è compilare come al solito.
Controllo della compilazione
Il comando build può raggiungere l'obiettivo di controllare la compilazione tramite tags. Esistono sotto forma di istruzioni nel codice sorgente. Ecco un esempio, il file product.go
// +build product
package main
import "fmt"
func main() {
fmt.Println("product")
}Il file debug.go
// +build debug
package main
import "fmt"
func main() {
fmt.Println("debug")
}Entrambi hanno un'istruzione // +build che indica in quali circostanze verranno compilati. Il formato di base è
// +build tag1 tag2
package pkg_nameCi sono alcune regole che devono essere seguite
- Deve esserci uno spazio tra
//e+build - Deve essere posizionato sopra la dichiarazione del pacchetto
- Deve esserci una riga vuota tra esso e la dichiarazione del pacchetto
Inoltre, può raggiungere lo scopo del controllo logico attraverso semplici spaziature: lo spazio indica OR, la virgola indica AND, ! indica NOT. Ad esempio, il seguente esempio
// +build windows linux
package pkg_nameIndica che il file corrente verrà compilato su piattaforme windows o linux.
// +build windows,amd64,!cgo linux,i386,cgo
package pkg_nameQuesto esempio indica che verrà compilato solo su piattaforma windows con architettura amd64 e senza cgo abilitato, oppure su piattaforma linux con architettura i386 e con cgo abilitato. Se semplicemente non desideri che un file partecipi alla compilazione, puoi utilizzare ignore.
// +build ignore
package pkg_namePossono anche esistere istruzioni su più righe
// +build windows
// +build amd64
package pkg_nameLe istruzioni su più righe vengono elaborate in modalità AND. Per tag come piattaforma e architettura, go li passerà automaticamente durante la compilazione. Possiamo anche passare tag personalizzati. Prendiamo i due file iniziali come esempio
$ go build -tags="debug" . && ./golearn.exe
debug
$ go build -tags="product" . && ./golearn.exe
productCome puoi vedere, passando tag diversi si ottengono output diversi. L'obiettivo del controllo della compilazione è raggiunto.
run
Il comando run, come build, compilerà il codice sorgente. La differenza è che il comando run eseguirà direttamente dopo la compilazione. Il comando run, per accelerare la velocità di compilazione, non genera informazioni di debug durante il processo di compilazione, quindi non supporta il debug e genera solo un file binario temporaneo, solitamente memorizzato nella directory GOTMEPDIR, ad esempio /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.Supporta anche i flag di compilazione del comando build e fornisce un parametro -exec per indicare quale programma utilizzare per eseguire il file binario. [arguments...] si riferisce ai parametri di esecuzione del programma. Ecco un esempio
package main
import (
"fmt"
"os"
)
var (
Version string
)
func main() {
fmt.Println(Version)
fmt.Println(os.Args[1:])
}Esegui con go run
$ go run -ldflags="-X main.Version=$(git describe --always)" main.go hello
5e3fd7a
[hello]Nel complesso, l'utilizzo non è molto diverso da go build, quindi non mi dilungherò ulteriormente.
tool
Il comando tool non ha alcuna funzione di per sé. Il suo scopo è chiamare direttamente gli strumenti nella directory cmd/. Ad esempio, cmd/compile è il compilatore integrato. Tramite go tool è possibile chiamare direttamente questi strumenti senza dover eseguire manualmente i file binari di questi strumenti.
$ go tool -h
usage: go tool [-n] command [args...]Usa il parametro -n per stampare tutti i parametri di comando supportati
$ go tool -n
addr2line
asm
buildid
cgo
compile
covdata
cover
doc
fix
link
nm
objdump
pack
pprof
test2json
trace
vetQuesti strumenti sono memorizzati nella directory GOROOT/pkg/tool e sono raggruppati in base al sistema operativo e all'architettura CPU. Come 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*Utilizza il formato go doc cmd/command per visualizzare l'utilizzo di ogni comando. Ad esempio
$ 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.
...I flag supportati da cmd/compile sono gli stessi parametri supportati da gcflags menzionati in precedenza. La differenza tra go tool compile e go build è che il primo è solo responsabile della compilazione e può accettare solo file come parametri. Il secondo può accettare cartelle, pacchetti e file come parametri e non si limita a compilare il codice sorgente, ma si occupa anche di collegare i file, eliminare i file inutili, ecc. Il primo è una parte del secondo. Possiamo stampare i comandi eseguiti durante il processo di 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
...Nel processo puoi vedere che c'è /golang/pkg/tool/windows_amd64/compile.exe, che è la chiamata al compilatore. Oltre a compile, ci sono molti altri strumenti che possono essere chiamati. Molti comandi go sono in realtà i loro alias.
clean
Il comando clean viene utilizzato per eliminare i file oggetto generati durante il processo di compilazione
$ go clean -h
usage: go clean [clean flags] [build flags] [packages]
Run 'go help clean' for details.Supporta i seguenti flag
-i: elimina i file archivio o i file binari corrispondenti-n: stampa i comandi da eseguire durante il processo di pulizia ma non li esegue effettivamente-x: stampa ed esegue i comandi da eseguire durante il processo di pulizia-r: esegue la pulizia ricorsivamente tramiteimport path-cache: elimina tutta la cache generata dago build-testcache: elimina tutta la cache di test generata-modcache: elimina tutta la cache dei moduli scaricati-fuzzcache: elimina la cache generata dafuzz test.
Quando si utilizza go tool compile, si chiama direttamente il comando del compilatore e non si eseguono molte operazioni di pulizia come go build, generando così file oggetto. Ad esempio, eseguendo il seguente comando
go tool compile -N -S -l main.goverrà generato un file chiamato main.o. Utilizza il comando go clean per eliminarlo. Oppure usa il parametro -n per stampare i comandi da eseguire.
$ 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.exeElimina la cache di compilazione. Eliminerà la cache di compilazione generata nella directory GOCACHE
$ go clean -cache -n
rm -r /cache/00 /cache/01 /cache/02Elimina la cache generata da fuzz test. Queste cache sono memorizzate per impostazione predefinita nella directory GOCACHE/fuzz/
$ go clean -fuzzcache -n
rm -rf /cache/fuzzfix
Al momento della stesura di questo articolo, il linguaggio go esiste da dieci anni. Durante il processo continuo di aggiornamento e modifica del linguaggio, è inevitabile che si verifichino incompatibilità dovute a cambiamenti nelle API. Il comando fix è nato per questo scopo. Rileverà le API obsolete nei file sorgente e le sostituirà con le nuove API.
$ go fix -h
usage: go fix [-fix list] [packages]
Run 'go help fix' for details.Supporta cartelle, nomi di file e directory come parametri. Accetta il flag -fix per passare parametri che indicano quale tipo di modifica eseguire. È possibile visualizzare i valori disponibili tramite il 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.Ecco un esempio. Il codice sorgente utilizza il pacchetto golang.org/x/net/context
package main
import (
"fmt"
"golang.org/x/net/context"
)
func main() {
background := context.Background()
fmt.Println(background.Err())
}Correggi con go fix per sostituirlo con il pacchetto context della libreria standard. Puoi utilizzare il seguente comando per eseguire la sostituzione
$ go fix -fix context main.goPuoi anche non sostituire e vedere le variazioni del file prima e dopo.
$ 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() {Il linguaggio go è nato da oltre dieci anni e ha solo nove parametri di sostituzione disponibili. Questo mostra che la compatibilità è stata mantenuta abbastanza bene.
fmt
Il comando fmt è lo strumento di formattazione integrato del linguaggio go, utilizzato per formattare i file di codice sorgente go.
$ go fmt -h
usage: go fmt [-n] [-x] [packages]
Run 'go help fmt' for details.Visualizza la documentazione dettagliata con il comando go doc gofmt
$ 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 utilizza tab per l'indentazione e spazi per l'allineamento. Per impostazione predefinita, il codice formattato verrà prodotto sull'output standard, non sovrascrivendo il file originale. Il comando go fmt utilizza effettivamente il comando gofmt, che è un file binario indipendente situato nella directory GOROOT/bin.
$ ls $GOROOT/bin -1
go.exe*
gofmt.exe*Aggiungendo il flag -n al comando go fmt puoi sapere quali comandi verranno eseguiti.
$ go fmt main.go
/golang/bin/gofmt.exe -l -w main.goCome puoi vedere, go fmt è in realtà un alias di gofmt -l -w. Il comando gofmt ha i seguenti parametri
-d: produce le differenze del file prima e dopo la formattazione-e: produce tutti gli errori-l: produce il nome del file che è stato modificato-r: applica le regole di formattazione-s: tenta di semplificare il codice-w: sovrascrive il file sorgente. Se si verifica un errore, ripristina il backup
Supponiamo ora di avere il seguente file sorgente
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")}Puoi visualizzare le variazioni con il parametro -d
$ 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!")
+}Il parametro -l produrrà il nome del file che verrà modificato
$ gofmt -l .
main.goSe ci sono errori di sintassi, il parametro -e può produrre output più dettagliati
$ 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 applicherà le modifiche al file sorgente
$ gofmt -l -w .
main.go
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")
}Puoi notare che, come strumento di formattazione, gofmt non fornisce alcuna configurazione personalizzata. Al contrario, il formatter prettify dedicato all'abbellimento del codice js fornisce numerose configurazioni per la formattazione del codice. Questo riflette l'atteggiamento ufficiale di go: non vuoi personalizzazioni, il codice di tutti dovrebbe avere lo stesso stile. Almeno c'è un vantaggio: non devi adattarti alle abitudini degli altri quando leggi il codice. Tuttavia, mantiene effettivamente un elemento personalizzabile: le regole di sostituzione del codice formattato. Le regole sono personalizzabili e il formato è il seguente
pattern -> replacementAd esempio, per rimuovere le parentesi ridondanti
(a) -> aVisualizza le variazioni del file
$ 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!")
}Come puoi vedere, gofmt rimuoverà le parentesi ridondanti.
get
Il comando get è assolutamente uno dei più utilizzati durante lo sviluppo go. Il suo scopo è scaricare il codice sorgente del pacchetto specificato nella directory corrispondente a GOMODCACHE.
$ go get -h
usage: go get [-t] [-u] [-v] [build flags] [packages]
Run 'go help get' for details.-u: tenta di aggiornare la versione secondaria e la versione patch del pacchetto. Se comporta un cambiamento di versione principale, comev1->v2, non verrà aggiornato.-t: aggiorna la versione delle dipendenze nei test-v: produce i pacchetti compilati. In realtà è uno dei parametri dibuild flags
Nei tempi antichi, go get aveva una funzione simile a go install: scaricava e compilava questi pacchetti. Tuttavia, con la nascita e il perfezionamento dei moduli go, questa funzione è stata gradualmente abbandonata. Ora il comando get è più comunemente utilizzato per scaricare e risolvere le dipendenze dei moduli go. Quindi puoi vedere che il comando go get supporta anche flag di compilazione come build flags. E se provi a utilizzare go get al di fuori di un modulo come faresti con go install, ti avviserà che questo utilizzo è deprecato.
$ 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'.Non si sa perché questi siano ancora mantenuti nella descrizione della documentazione. Esaminando il codice sorgente del comando get, scoprirai che ha mantenuto quei flag precedenti.
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
)Tornando al punto, il comando get scaricherà il codice sorgente del pacchetto specificato nella directory globale delle dipendenze locale, ovvero la directory corrispondente a GOCACHE, e registrerà le informazioni nei file go.mod e go.sum. Il primo è responsabile della registrazione della versione e il secondo registra il checksum sha1 per garantire la sicurezza. Il comando get si basa effettivamente su VCS, ovvero il sistema di controllo versione locale. Supporta complessivamente i seguenti
- git
- hg (Mercurial)
- bzr (Bazaar)
- svn
- fossil
Tra questi, per impostazione predefinita supporta solo git e hg. È possibile configurare in GOVCS. Il formato è il seguente
GOVCS=github.com:git,example.com:hg,*:git|hg,*:allGOVCS supporta solo git e hg come VCS. Gli altri tre devono essere configurati in GOPRIVATE.
Il comando go get ha complessivamente i seguenti utilizzi. Puoi passare direttamente l'indirizzo della dipendenza come parametro
$ go get golang.org/x/netPuoi anche specificare una versione
$ go get golang.org/x/net@0.17.0Specificare l'ultima versione
$ go get golang.org/x/net@latestTentare di aggiornare la versione
$ go get -u golang.org/x/netRimuovere una dipendenza
$ go get golang.org/x/net@noneQuesti sopra sono utilizzati per gestire dipendenze ordinarie. Può anche essere utilizzato per gestire dipendenze non ordinarie, come aggiornare la versione del linguaggio 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.3Può anche essere utilizzato per aggiornare la versione della toolchain go
$ go get toolchain@latestQuando utilizzi go get per aggiornare le versioni di go e della toolchain, installeranno la nuova versione di go nella directory GOMODCACHE/golang.org/
$ ls $(go env GOMODCACHE)/golang.org -1
'toolchain@v0.0.1-go1.21.3.windows-amd64'/
x/A questo punto, modificando manualmente GOROOT puoi passare alla versione specificata.
install
Il comando install è simile al comando get. Entrambi sono utilizzati per scaricare dipendenze di terze parti. La differenza è che il comando get scarica il codice sorgente, mentre il comando install compilerà il codice sorgente in un file binario eseguibile per la macchina locale. Il percorso di memorizzazione del file binario è prima nella directory GOBIN, poi in GOPATH/bin. La funzione principale di questo comando è scaricare alcuni strumenti da riga di comando pubblici di terze parti. Grazie alla velocità di compilazione e alla portabilità del linguaggio go, non è necessario scaricare file binari, ma scaricare direttamente il codice sorgente e compilarlo localmente.
$ go install -h
usage: go install [build flags] [packages]
Run 'go help install' for details.Il comando install accetta flag di compilazione e nomi di pacchetti come parametri. Con gomod abilitato, il nome del pacchetto deve includere il numero di versione. Ad esempio, per scaricare il debugger 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/Innanzitutto scaricherà il codice sorgente nel percorso memorizzato in GOMODCACHE, proprio come il comando get. Quindi passerà alla directory di lavoro temporanea per compilarlo. Dopo aver completato la compilazione, sposterà il file binario nella directory GOPATH/bin e infine eliminerà la cartella temporanea. Il comando install ha anche una limitazione: il pacchetto scaricato deve essere il pacchetto di ingresso del progetto, ovvero deve contenere il file di ingresso main.go. Altrimenti, ti avviserà che non può essere installato. Ad esempio, utilizzando go install per scaricare 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 è una libreria di dipendenze per framework web, non uno strumento da riga di comando, quindi naturalmente non ha un file di ingresso e l'installazione fallirà.
list
Il comando list elencherà i pacchetti nella posizione specificata, uno per riga, e supporta l'output formattato personalizzato. Supporta molti parametri. Il prerequisito per il suo utilizzo è che deve essere all'interno di un progetto che supporta gomod.
$ go list -h
usage: go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
Run 'go help list' for details.I parametri supportati sono i seguenti
-f: parametro di formattazione-json: output in formato json-compiled: mostra tutti i pacchetti che verranno compilati dal compilatore-deps: mostra il nome di ogni pacchetto e di ogni sua dipendenza-test: mostra il pacchetto di test di ogni pacchetto-e: produce normalmente quando incontra pacchetti con errori-find: non analizza le relazioni di dipendenza di questi pacchetti-export: quando si utilizza questo parametro, imposta il valore del campoPackage.Exportdella struct sul file contenente le informazioni di esportazione più recenti del pacchetto specificato e imposta il valore del campoPackage.BuildIDsulBuildIDdel pacchetto. Principalmente utilizzato per l'output formattato.
Parametri di informazioni sul modulo
-m: produce moduli invece di pacchetti-versions: mostra tutte le informazioni disponibili di un modulo-retracted: mostra le versioni ritirate di un modulo
Il parametro [packages] può essere un nome di pacchetto specificato o una cartella. Può anche essere all, che indica ovunque. Quando si utilizza il parametro -m, all indica tutte le dipendenze citate dal modulo corrente.
Ad esempio, il file corrente contiene solo un file main.go con una sola riga di codice che produce "hello world". Dopo aver eseguito go list -deps ., produce tutti i pacchetti di dipendenza dal progetto corrente a fmt e alle sue dipendenze.
$ 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
golearnOppure produce tutte le dipendenze del modulo nel progetto corrente
$ 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
L'output del comando list è per riga. Ogni riga di output è un pacchetto. L'ufficio fornisce il parametro -f per personalizzare il formato di output della riga. Il valore accettato è la sintassi del template definita dal pacchetto del motore template template/text. Ad esempio, il seguente esempio
-f "package {{ .Dir }} {{ .Name }}"Ogni pacchetto iterato verrà passato nella forma della seguente struct. Tutti i campi di questa struct possono essere utilizzati come parametri del 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 si itera sui moduli, verrà passato nella forma della seguente struct. Tutti i suoi campi possono anche essere utilizzati come parametri del 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
}Visualizza tutti i pacchetti
$ 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 toolVisualizza i moduli
$ go list -m -f "mod {{.Path}} {{.Version}} {{.GoVersion}} {{.GoMod}}"
mod golearn 1.21.3 /golearn/go.modmod
go mod è un comando dedicato alla gestione dei moduli 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.Ha i seguenti sottocomandi
download: scarica tutte le dipendenze indicate nel filego.modnella cache localeedit: modifica il filego.mod. L'interfaccia a riga di comando fornita è principalmente destinata ad essere utilizzata da altri strumenti o script.init: inizializza un progetto gomod nella directory correntetidy: scarica le dipendenze mancanti ed elimina le dipendenze inutilizzategraph: produce il grafico delle dipendenzeverify: verifica le dipendenze localiwhy: spiega perché questi moduli sono dipendentivendor: esporta le dipendenze del progetto nella directory vendor
init
$ go help mod init
usage: go mod init [module-path]Il comando init viene utilizzato per inizializzare un progetto gomod. Il suo unico parametro è il percorso del modulo, che verrà utilizzato come base per scaricare le tue dipendenze in futuro. La sua regola di denominazione è generalmente
domain_name/user_name/repo_nameAd esempio, poiché la maggior parte delle persone mette i propri progetti su github, potrebbe essere
github.com/jack/gotourNon è consigliabile utilizzare simboli speciali come percorso del modulo. Ecco un caso d'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]Il comando tidy rimuoverà le dipendenze inutili in go.mod, ovvero le dipendenze non referenziate, e scaricherà le dipendenze referenziate ma non esistenti. Supporta i seguenti parametri
-v, produce le dipendenze del modulo eliminate-e, ignora gli errori durante il processo e continua l'esecuzione-x, produce il processo di esecuzione-go=version, aggiorna la versione go nel filego.mod-compact=version, mantiene eventuali checksum aggiuntivi necessari dalla versione Go principale specificata per caricare correttamente il grafico del modulo e causerà errori se tidy carica qualsiasi pacchetto importato da una versione del modulo diversa con la versionegodi quella versione. Questo parametro è raramente utilizzato e generalmente causa errori solo durante i cambiamenti di versione. Puoi dare un'occhiata a questa risposta su stackoverflow go modules - go mod tidy error message: "but go 1.16 would select" - Stack Overflow
Ecco un esempio di utilizzo
$ 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]Sebbene il nome del comando download significhi download, scarica solo le dipendenze nella cache delle dipendenze locale e non modifica il file go.mod. Il suo scopo è pre-scaricare le dipendenze nella cache dei file locale. Se desideri scaricare una determinata dipendenza, si consiglia di utilizzare go get o go mod tidy.
Ecco alcuni esempi di utilizzo
$ 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)Senza parametri, scaricherà tutte le dipendenze presenti nel file go.mod ma non nella cache delle dipendenze locale. Se non c'è nulla da scaricare, produrrà
go: no module dependencies to downloadedit
$ go help mod edit
usage: go mod edit [editing flags] [-fmt|-print|-json] [go.mod]edit è un'interfaccia a riga di comando per modificare il file go.mod, solitamente utilizzata da altri programmi. Alcuni editor IDE utilizzano questi comandi per fornire supporto gomod. Supporta i seguenti parametri
-module, modifica il percorso del modulo-go=version, modifica la versione go attesa-require=path@version, aggiunge una dipendenza-droprequire=path@version, rimuove una dipendenza-exclude=path@version, aggiunge una dipendenza esclusa-dropexclude=path@version, rimuove una dipendenza esclusa-replace=old@version=new@version, aggiunge una dipendenza sostituita-dropreplace=old@version, rimuove una dipendenza sostituita-retract=version, aggiunge un elemento di rollback della versione-dropretract=version, rimuove un elemento di rollback della versione
Ci sono anche altri parametri per la visualizzazione
-print, produce il contenuto del file-json, produce in formato json
Ad esempio
$ 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]Il comando graph produrrà il grafico delle dipendenze del progetto corrente. La sua leggibilità è scarsa e nella maggior parte dei casi non è destinato alla lettura umana. I risultati vengono solitamente elaborati e visualizzati in forma visiva. Ogni riga è una dipendenza, il formato è il seguente
Citante CitatoAd esempio
golearn go@1.21.3Supporta anche due parametri
-go=version, carica il grafico delle dipendenze utilizzando una determinata versione go. Il suo valore non può essere inferiore alla versione nel filego.mod.-x, mostra i comandi eseguiti durante il processo.
Ecco un semplice esempio di utilizzo
$ 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 era una soluzione alternativa a gopath prima dell'introduzione di gomod. Ogni progetto go aveva una directory vendor, che memorizzava le dipendenze di ogni progetto separatamente nel formato domain/user/project, proprio come il gonfio node_module di nodeJs. Questo modo di gestire le dipendenze sembra davvero stupido ora, ma a quel tempo non c'era una soluzione migliore. Il motivo per cui vendor è mantenuto è perché go mantiene la promessa di compatibilità con le versioni precedenti. Alcuni vecchi progetti, incluso il codice sorgente go, potrebbero ancora utilizzare vendor.
Tornando al punto, vendor è un sottocomando di go mod che può esportare le dipendenze globali referenziate dal modulo corrente nella directory vendor.
$ go mod vendor -h
usage: go mod vendor [-e] [-v] [-o outdir]
Run 'go help mod vendor' for details.Ha i seguenti parametri
-o: specifica il percorso della cartella di output-v: produce ogni dipendenza-e: non esce quando si verifica un errore e continua
Ecco un esempio. Prima usa go list -m all per visualizzare le dipendenze referenziate dal progetto corrente
$ 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.1Esporta nella directory vendor corrente
$ 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.v3La struttura della directory dopo l'esportazione è la seguente
└─vendor
├─github.com
│ ├─davecgh
│ │ └─go-spew
│ │ └─spew
│ ├─pkg
│ │ └─errors
│ ├─pmezard
│ │ └─go-difflib
│ │ └─difflib
│ └─stretchr
│ └─testify
│ └─assert
└─gopkg.in
| └─yaml.v3
|
|--modules.txtIl file modules.txt è un file che descrive tutti gli elementi di dipendenza, simile all'attuale go.mod.
verify
$ go help mod verify
usage: go mod verifyQuesto comando verificherà se le dipendenze del progetto sono state modificate dopo essere state scaricate localmente. Ad esempio, se non ci sono problemi, produrrà all modules verified
$ go mod verify
all modules verifiedAltrimenti segnalerà dove sono avvenute le modifiche e terminerà il comando con uno stato anormale. Ad esempio
$ 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...Spiega perché questo pacchetto è dipendente, in realtà produce il grafico delle dipendenze ad esso relativo. Ad esempio
$ go mod why gorm.io/gorm
# gorm.io/gorm
golearn
gorm.io/gormPer impostazione predefinita, analizzerà solo l'importazione da main. Aggiungendo il parametro -m può analizzare la situazione di importazione di ogni pacchetto.
work
Il comando work è uno strumento di sviluppo locale per la gestione di più moduli 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
Il sottocomando init viene utilizzato per inizializzare un workspace. Questo comando creerà un file chiamato go.work
$ go work init -h
usage: go work init [moddirs]
Run 'go help work init' for details.Accetta il parametro [moddirs] per specificare quali moduli includere nella gestione. Ad esempio
$ go work init ./service ./apiuse
Il sottocomando use viene utilizzato per aggiungere directory di moduli gestiti a 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.Accetta [moddirs] come parametro e c'è anche -r che indica di cercare ricorsivamente i moduli nel percorso [moddirs]. Ad esempio
$ go work use -r ./oss-api ./multi_modulesedit
La funzione del sottocomando edit è la stessa di go mod edit, entrambe lasciate all'interfaccia a riga di comando per essere utilizzate da altri strumenti e script.
$ 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 directoriesI parametri sono i seguenti
-fmt, formatta il filego.work-use,-dropuse, aggiunge e rimuove percorsi di moduli-replace=old[@v]=new[@v],-dropreplace=old[@v]=new[@v], utilizzati per aggiungere e rimuovere moduli da sostituire-go,-toolchain=name, specifica la versione go e la toolchain da utilizzare-print, stampa le modifiche finali senza riscrivere il file-json, produce in formatojson, non può essere utilizzato con-print. La struttura del tipo corrispondente è la seguentegotype 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 }
Alcuni esempi di utilizzo sono i seguenti, output formattato
$ go work edit -fmt -print
go 1.22.0
use (
./ab/cd
./auth
./user
)Output json
$ go work edit -fmt -json
{
"Go": "1.22.0",
"Use": [
{
"DiskPath": "./ab/cd"
},
{
"DiskPath": "./auth"
},
{
"DiskPath": "./user"
}
],
"Replace": null
}sync
Il sottocomando sync viene utilizzato per ripristinare l'elenco dei moduli in go.work nei vari moduli nel workspace.
$ go help work sync
usage: go work sync
Sync syncs the workspace's build list back to the
workspace's modulesQuesto processo avviene principalmente dopo il completamento dello sviluppo locale, quando ogni modulo ha completato il lavoro di rilascio. A questo punto, utilizzando sync, aggiornerà le dipendenze in go.mod di tutti i moduli nel workspace in base alle relazioni di dipendenza di ciascun modulo, eliminando la necessità di aggiornarle manualmente.
vendor
Il comando vendor copierà tutte le librerie di dipendenze dei moduli nel workspace nella directory vendor.
$ go work help vendor
usage: go work vendor [-e] [-v] [-o outdir]La funzione è la stessa di go mod vendor, non mi dilungherò ulteriormente.
vet
Il comando vet è uno strumento di controllo statico degli errori per il codice sorgente del linguaggio go, proprio come gli strumenti lint di altri linguaggi, come 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.Ecco un esempio semplice. Supponiamo di avere il seguente codice sorgente
$ cat main.go
package main
import "fmt"
func main(){
fmt.Println("hello world!"
}Esegui go vet senza parametri nella directory同级
$ go vet
vet: ./main.go:6:28: missing ',' before newline in argument list (and 1 more errors)vet segnalerà quale file e quale riga ha quale problema. Supporta flag di compilazione come parametri, come -n e -x, e supporta pacchetti, cartelle e nomi di file come parametri.
$ go vet .
$ go vet main.go
$ go vet ./cmd
$ go vet runtimeVisualizza i parametri e le spiegazioni più dettagliati con il seguente comando.
$ 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
......Il comando go tool vet non può essere utilizzato direttamente per controllare il codice. Dovresti usare go vet. Il parametro [vet flag] di go vet supporta l'impostazione di analizzatori di codice. I valori disponibili sono i seguenti
asmdecl Controlla se i file assembly corrispondono alle dichiarazioni go
assign Controlla se ci sono variabili inutili
atomic Controlla se l'atomicità viene violata quando si usa sync/atomic
bools Controlla se gli operatori logici sono usati erroneamente
buildtag Controlla i build tag
cgocall Controlla comportamenti che violano le regole di passaggio dei puntatori cgo
composites Controlla strutture composite non inizializzate, come map, chan
copylocks Controlla se si verifica una copia del valore di un lock
directive Controlla le istruzioni della toolchain go
errorsas Controlla se viene passato un tipo non puntatore o non error a errors.As
framepointer Controlla se il codice assembly ottimizzato dalla compilazione cancella il frame pointer prima di salvarlo
httpresponse Controlla se httpresponse è usato erroneamente
ifaceassert Controlla l'asserzione di tipo da interfaccia a interfaccia
loopclosure Problemi di riferimento delle variabili di ciclo
lostcancel context.WithCancel non usa la funzione cancel
nilfunc Controlla se ci sono confronti inutili tra funzioni e nil
printf Controlla se i parametri di formattazione di printf sono corretti
shift Controlla se ci sono shift uguali o superiori alla larghezza dell'intero
sigchanyzer Controlla chan os.Signal non bufferizzati
slog Controlla chiamate di log strutturati non valide
stdmethods Controlla se le firme dei metodi di interfacce note sono corrette
stringintconv Controlla la conversione di stringhe e interi
structtag Controlla se i tag delle struct sono corretti
testinggoroutine Controlla se viene utilizzata la协程 per chiamare testing.Fatal nei test
tests Controlla gli usi comuni errati di test ed esempi
timeformat Controlla se il formato di (time.Time).Format o time.Parse è corretto
unmarshal Passa tipi non puntatore o non interfaccia a unmarshal
unreachable Controlla il codice non raggiungibile
unsafeptr Controlla la conversione errata da uintptr a unsafe.Pointer
unusedresult Controlla i valori di ritorno di funzioni non utilizzatiSono tutti analizzatori che analizzano un punto specifico. Ad esempio, l'analizzatore timeformat controlla se il formato di chiamata di time.Format è conforme alla sintassi corretta. Per impostazione predefinita, tutti gli analizzatori sopra menzionati sono abilitati. Per abilitarne uno singolarmente, è possibile utilizzare il seguente formato
$ go vet -timeformat main.goPer disabilitarne uno singolarmente
$ go vet -timeformat=false main.goIl codice sorgente di questi analizzatori si trova in cmd/vendor/golang.org/x/tools/go/analysis/passes. Ogni analizzatore è una trappola comune nel linguaggio go, quindi è altamente consigliato utilizzare il comando vet per controllare il tuo codice. Oltre a questi, supporta anche alcuni altri flag
-V, stampa solo la versione ed esce-json, produce in formato json-c=n, mostra il numero specificato di righe di conflitto nel contesto (sembra non avere alcun effetto)
Ci sono anche analizzatori esterni, come shadows, che è responsabile del rilevamento di problemi di nascondimento di variabili con nomi di variabili brevi. Poiché è esterno, deve essere scaricato con go install
$ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latestIl formato di utilizzo è il seguente
$ 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.Il comando test è il comando fornito dalla toolchain del linguaggio go per le funzionalità di test. Questa funzione è molto importante. Per un software, test completi sono indispensabili. Qui viene introdotta solo brevemente come utilizzare il comando test. Per ulteriori informazioni sui test, visita: 测试
Oltre a supportare i parametri di compilazione del comando build, test supporta anche i seguenti parametri
-args, parametri di ingresso del programma-c, compila il file binario di test del pacchetto corrente nella directory corrente ma non lo esegue, nominato comepkg.test-exec, esegue alcuni altri comandi prima dell'inizio del test-json, lo stile di output del test diventa json-o, specifica il nome del percorso del file binario di test
Supporta anche molti testflag. Visualizza tutti i testflag con il comando help
$ go help testflag
Il comando `go test` accetta sia flag che si applicano al `go test` stesso,
sia flag che si applicano al file binario di test generato.
Il comando `go test` riconosce i seguenti flag e li utilizza per controllare l'esecuzione di qualsiasi test:
-bench regexp
-benchtime t
-count n
......Ecco alcuni comunemente utilizzati
-v, produce i risultati di test di ogni caso di test.-timeout duration, tempo di scadenza dell'esecuzione del test-skip regexp, salta i casi di test specificati-short, riduce il tempo di esecuzione per quei casi di test che richiedono molto tempo-shuffle, mescola l'ordine di esecuzione di tutti i casi di test-run regexp, esegui i casi di test specificati-list regexp, elenca ogni caso di test-cpu 1,2,4, specifica il numero di cpu-count n, specifica quante volte eseguire ogni caso di test
L'uso più semplice è senza parametri. Esegue tutti i casi di test nel pacchetto corrente e produce i risultati.
$ ls *_test.go
hello_test.go
$ go test
PASS
ok golearn 0.522sSpecifica un file di test
$ go test hello_test.go
ok command-line-arguments 0.041sAggiungendo il parametro -v puoi visualizzare un output più dettagliato. È abbastanza comune.
$ go test -v hello_test.go
=== RUN TestHello
hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok command-line-arguments 0.041sSpecifica un caso di test
$ go test -v -run TestHello
=== RUN TestHello
hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok golearn 0.028sDurante il test, il comando test ha due modalità. Prima parliamo della modalità cartella. Quando esegui il comando test senza il parametro package, eseguirà il test in modalità cartella. Ad esempio, i seguenti comandi
$ go test
$ go test -vIn questa modalità, la cache di test è disabilitata. L'altra modalità è la modalità elenco. Quando il parametro package non è vuoto, eseguirà il test in modalità elenco. La differenza con la prima è se la cache di test è abilitata. Ad esempio, i seguenti
$ go test -v .
$ go test -v ./...
$ go test .
$ go test -v net/httpIn modalità elenco, go compilerà ed eseguirà i file di test di ogni pacchetto nel pacchetto specificato in file binari. Per evitare di eseguire ripetutamente i test, go memorizzerà i risultati nella cache per impostazione predefinita e non ricompilerà durante la seconda esecuzione. La cache verrà abilitata per impostazione predefinita quando si utilizzano i seguenti parametri
-benchtime-cpu-list-parallel-runshort-timeout-failfast-v
Utilizzando parametri diversi da questi è possibile disabilitare la cache. Il metodo consigliato ufficialmente è utilizzare -count=1 per disabilitare la cache. Ad esempio
$ go test -v -count=1 ./...Direttive
A differenza dei comandi, le direttive go esistono nel codice sorgente in forma di codice hardcoded. Hanno un altro nome più tecnico: direttive di compilazione (pragma directives).
I compilatori e i linker cambieranno il loro comportamento a causa di esse, raggiungendo così l'effetto di controllare la compilazione, simile alle macro nel linguaggio C. Naturalmente, non tutte le direttive sono utilizzate per influenzare la compilazione. Alcune sono utilizzate per altri comportamenti funzionali. Ad esempio, la direttiva generate è solitamente utilizzata per funzionalità di generazione di codice. Queste direttive esistono solitamente sotto forma di commenti e iniziano con il prefisso //go:, senza alcuno spazio nel mezzo, come la direttiva //go:generate. Tutti i tipi di direttive sono divisi in due categorie
- Direttive funzionali, queste sono direttive funzionali fornite da go che possono essere utilizzate liberamente, come
generate,embed,build. - Direttive del compilatore, queste direttive devono essere utilizzate con cautela. Un uso improprio può portare a risultati imprevedibili.
Ad eccezione delle direttive funzionali, la maggior parte delle direttive può agire solo sulle firme delle funzioni. Per le direttive del compilatore, è possibile eseguire il comando go doc compile per visualizzare le sue direttive. Per tutte le direttive, è possibile trovare informazioni su di esse in cmd/compile/internal/ir/node.go: 440.
generate
$ go help generate
usage: go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]La direttiva generate, come suggerisce il nome, è relativa alla generazione. Solitamente il suo scopo è eseguire comandi che generano codice e aggiornano il codice sorgente, ma in realtà può eseguire qualsiasi comando. Inoltre, a differenza di altre direttive, generate ha un comando dedicato per eseguire tutte le direttive generate presenti nei file sorgente. Può accettare nomi di file o nomi di pacchetti come parametri di input per indicare quali file eseguire le direttive generate. Ecco i suoi altri parametri.
-run=regex, esegue la direttiva generate specificata-skip=regex, salta la direttiva generate specificata-n, stampa i comandi che verranno eseguiti-x, stampa i comandi eseguiti durante il processo-v, produce i file elaborati
Inoltre, i comandi eseguiti nella direttiva generate supportano anche i seguenti parametri incorporati
$GOARCH, architettura cpu$GOOS, sistema operativo$GOFILE, nome file$GOLINE, numero di riga$GOPACKAGE, nome pacchetto$GOROOT, go root$DOLLAR, simbolo del dollaro$PATH, variabile d'ambiente path
Ecco un esempio. Non c'è codice, solo un commento
package main
//go:generate echo "hello world!"Esegui il comando
$ go generate .
hello world!Questo esempio esegue il comando go
package main
//go:generate go versionEsegui il comando
$ go generate .
go version go1.21.3 windows/amd64La direttiva generate può essere utilizzata per eseguire qualsiasi comando, come swagger per generare documentazione API o Wire per generare codice IOC. Tuttavia, questa direttiva non è adatta per eseguire comandi particolarmente complessi. È adatta per eseguire comandi brevi. Se ci sono requisiti complessi, è possibile utilizzare script o makefile come sostituti.
embed
La direttiva embed è stata aggiunta nella versione 1.16. Il suo scopo è includere file statici nel file binario, come modelli HTML. Il suo formato è il seguente
//go:embed patternpattern può essere un'espressione glob, una cartella o un file specifico. Ecco un esempio
package main
import "embed"
//go:embed *
var static embed.FSLa direttiva embed richiede di essere posizionata sopra una variabile globale di tipo embed.Fs. Nota che deve essere una variabile globale e per utilizzarla è necessario importare il pacchetto embed. In questo esempio, * rappresenta che tutti i file nella cartella corrente verranno inclusi nel file binario, ma non consentirà cartelle che iniziano con ..
L'esempio seguente mostra come leggere il contenuto da un file incorporato
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))
}Ha solo tre metodi e l'utilizzo non è diverso da un normale file system. Poiché implementa l'interfaccia io/Fs, può anche essere passato come oggetto 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)L'esempio seguente mostra come incorporare un file html tramite la direttiva embed e accedervi tramite un servizio 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)
}Il risultato dell'accesso è il seguente
$ 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>La direttiva embed supporta anche che il tipo di variabile globale possa essere []byte. Ecco un esempio
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)
}L'effetto realizzato è simile all'esempio precedente.
$ 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
Nella sezione build-Controllo della compilazione, è stato discusso come utilizzare la direttiva // +build per controllare il comportamento di compilazione. La direttiva //go:build è stata introdotta nella versione 1.17 con l'intenzione di sostituire la direttiva precedente, ma ora siamo alla versione 1.21 e non è ancora stata sostituita. Si stima che in futuro esisteranno in modo coesistente. La documentazione ufficiale ha anche una introduzione su questa nuova direttiva: build constraints. La sua funzione non è molto diversa dalla precedente, ma la sintassi è più rigorosa e supporta le espressioni booleane. Ecco un esempio
//go:build (linux && 386) || (darwin && !cgo)
package pkg_nameQuesto modo è molto più leggibile rispetto al precedente.
line
La direttiva line influenzerà il numero di riga, il numero di colonna e il nome del file della riga successiva. Il suo scopo si limita a questo e nella maggior parte dei casi potrebbe essere utilizzato per il debug di errori. Ad esempio, quando si verifica un errore, cambierà le informazioni prodotte dal compilatore.
package main
var a undefinedType
func main() {
}Normalmente, il compilatore produrrà
.\main.go:3:7: undefined: undefinedTypeMa se si utilizza la direttiva line, è diverso
package main
//line abc.go:10:100
var a undefinedType
func main() {
}Allora il suo output sarà
abc.go:10:106: undefined: undefinedTypeE a causa di ragioni storiche, la direttiva line è anche l'unica direttiva con un utilizzo diverso dalle altre direttive. Il suo formato è
//line filename:line:columnCome puoi vedere, non richiede il prefisso go:.
linkname
Questa operazione di direttiva può essere utilizzata per collegare funzioni o variabili globali di altri pacchetti, anche se sono di tipo privato. Questa operazione appare frequentemente nella libreria standard, specialmente in runtime. Alcune funzioni senza corpo di funzione sono implementate in questo modo, mentre altre funzioni con corpo di funzione vuoto sono implementate in assembly. Ecco il suo utilizzo. Il formato di utilizzo è il seguente
//go:linkname nome_tipo_collegato tipo_collegatoE prima di utilizzarla, ad esempio, importa il pacchetto unsafe. Ecco un esempio semplice di collegamento di un tipo privato nella libreria standard
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")))
}Output
15395306441938000233Collega la funzione privata runtime.memhash alla funzione che abbiamo dichiarato noi. Questa funzione non ha un corpo di funzione, solo una firma, e funge solo da supporto. La funzione memhash calcola il valore hash in base alla memoria dato un puntatore, un seed hash e un offset di memoria. Questo processo di collegamento viene completato durante la compilazione.
Se non è della libreria standard, la situazione è leggermente diversa. Ad esempio, c'è una funzione test nel pacchetto example. Prima del collegamento, è necessario importare anonimamente questo pacchetto.
package example
// Un tipo privato, inaccessibile dall'esterno.
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())
}Output
aCome puoi vedere, il collegamento è riuscito. Questo metodo può aggirare il sistema di moduli di go e fare ciò che si vuole, ma non è consigliabile utilizzarlo su larga scala, a meno che tu non sappia cosa stai facendo.
noinline
La direttiva noinline indica che una funzione non deve essere ottimizzata con l'inlining, anche se è molto semplice. Ecco un esempio semplice
package main
func val() string {
return "val"
}
func main() {
var c = val()
_ = c
}val è una funzione molto semplice che restituisce un letterale di stringa. Poiché è troppo semplice e il risultato è sempre prevedibile, durante la compilazione verrà ottimizzata dal compilatore nella seguente forma
package main
func main() {
var c = "val"
_ = c
}Ecco come appare in assembly. Come puoi vedere, non c'è chiamata alla funzione 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)
RETOra aggiungiamo la direttiva noinline
package main
//go:noinline
func val() string {
return "val"
}
func main() {
var c = val()
_ = c
}Ed ecco la sua forma 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
RETQuesta volta puoi vedere molto chiaramente la chiamata main.val, ed è esattamente la funzione della direttiva noinline: impedire l'inlining delle funzioni durante l'ottimizzazione del compilatore.
nosplit
La direttiva nosplit serve a saltare il rilevamento di overflow dello stack. Poiché il modello di schedulazione concorrente di go è di tipo preemptive, se una funzione esegue codice di livello molto basso e altre goroutine non dovrebbero essere preemptive quando chiamano questa funzione, è possibile utilizzare questa direttiva per indicarlo.
//go:nosplit
func nosplitFn()Dopo aver utilizzato questa direttiva, non ci sarà più crescita dello stack.
noescape
noescape, come si può facilmente intuire dal nome, è relativo all'escape. Il suo scopo è indicare che la funzione corrente non comporterà comportamenti di escape della memoria. Dopo l'esecuzione, tutte le risorse vengono recuperate e questa funzione deve avere solo una firma senza corpo di funzione. In questo caso, generalmente l'implementazione della funzione è realizzata in assembly.
Ad esempio, memhash utilizzato in precedenza utilizzerà questa direttiva
//go:noescape
//go:linkname memhash runtime.memhash
func memhash(p unsafe.Pointer, h, s uintptr) uintptrIn questo modo, il compilatore non eseguirà l'analisi di escape su di essa. La premessa è che devi garantire che non si verifichi escape. Se si verifica, non si sa quali saranno le conseguenze.
uintptrescapes
La direttiva uintptrescapes indica che i parametri di tipo uintptr in questa funzione sono stati convertiti in valori puntatore e sono fuggiti sull'heap e devono essere mantenuti in vita. Questa direttiva è generalmente utilizzata per alcune chiamate di sistema di basso livello. Nella maggior parte dei casi, non è necessario conoscerla.
//go:uintptrescapes
func nosplit(ptr uintptr) uintptrIn passato dovrebbe esserci stata una direttiva notinheaps utilizzata per indicare che un tipo non può allocare memoria sull'heap, ma non si sa in quale versione è stata rimossa.
norace
La direttiva norace indica che l'accesso alla memoria di una funzione non richiede più analisi delle race condition. Generalmente viene utilizzata quando si esegue codice di basso livello non adatto per l'analisi delle race condition.
//go:norace
func low_level_code(ptr uintptr) uintptrTIP
Alcune direttive sono limitate all'uso solo dal pacchetto runtime e non possono essere utilizzate dall'esterno. Coinvolgeranno cose più profonde. Se vuoi saperne di più, puoi vedere le informazioni su di esse in Runtime-only compiler directives.
