Skip to content

Kommandozeile

Befehle in Go enthalten eine vollständige Toolchain. Diese Befehle umfassen Dokumentation, Formatierung, Code-Überprüfung, Kompilierung, Tests, Abhängigkeitsmanagement und vieles mehr. Sie decken praktisch alle Aspekte der Go-Entwicklung ab.

text
bug         Fehler melden
build       Pakete und Abhängigkeiten kompilieren
clean       Objektdateien entfernen
doc         Dokumentation im Quellcode anzeigen
env         Go-Umgebungsvariablen anzeigen
fix         API-Kompatibilitätsprobleme aufgrund von Go-Versionsänderungen beheben
fmt         Quellcode formatieren
generate    Code-Generierung
get         Abhängigkeiten hinzufügen
install     Pakete installieren und kompilieren
list        Paket/Modul auflisten
mod         Modul-Wartungsbefehle
work        Workspace-Wartungsbefehle
run         Kompilieren und ausführen
test        Testen
tool        Angegebenes Go-Tool ausführen
version     Go-Versionsinformationen anzeigen
vet         Mögliche Probleme im Quellcode scannen und melden

Dieser Artikel beschreibt lediglich deren Verwendung. Alle Inhalte stammen aus der offiziellen Dokumentation. Für weitere Details besuchen Sie bitte cmd/go.

help

Der erste Befehl, den Sie kennenlernen sollten, ist help. Damit können Sie die Verwendung von Befehlen nachlesen. Es gibt zwei Verwendungsmöglichkeiten: Wenn Sie kurze Verwendungsinformationen erhalten möchten, fügen Sie dem Befehl das -h-Flag hinzu, zum Beispiel:

sh
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.

Go zeigt kurz die Verwendung des Befehls an. Es wird auch darauf hingewiesen, dass Sie den help-Befehl verwenden sollten, um detailliertere Informationen zu erhalten:

sh
$ 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'.

Nutzen Sie den help-Befehl, um mehr über die Verwendung von Befehlen zu erfahren.

doc

sh
$ 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 exported

Der doc-Befehl gibt Dokumentationskommentare für angegebene Pakete, Konstanten, Funktionen, Typen, Variablen, Methoden und sogar Strukturfelder aus. Ohne Argumente gibt er die Kommentare des aktuellen Pakets aus:

sh
$ go doc

Sie können auch ein bestimmtes Paket angeben, zum Beispiel die Dokumentation des runtime-Pakets:

sh
$ 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.
......

Oder einen bestimmten Typ:

sh
$ 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.
      ...

Oder eine bestimmte Funktion:

sh
$ 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.

Es gibt folgende häufig verwendete Flags:

  • -u: Private Typen anzeigen
  • -all: Alle Dokumentationen eines Pakets anzeigen
  • -short: Nur eine kurze Beschreibung pro Symbol
  • -src: Quellcode ausgeben
  • -cmd: Für Pakete, die zu Go-Befehlen gehören, auch die Code-Dokumentation innerhalb des Pakets ausgeben.

Zum Beispiel die Variable runtime.inf, die nicht exportiert ist:

sh
$ go doc -u runtime.inf
package runtime // import "runtime"

var inf = float64frombits(0x7FF0000000000000)

Der doc-Befehl hilft Ihnen, Dokumente bequemer zu lesen.

Eine weitere Möglichkeit, die Dokumentation von Befehlen zu lesen, besteht darin, den Quellcode zu lesen. Da einige Befehle nicht so detailliert dokumentiert sind, findet man im Quellcode oft ausführlichere Erklärungen. Da diese Befehle alle in Go geschrieben sind, ist das Lesen sehr bequem. Diese Befehle befinden sich im src/cmd-Paket, wobei jedes Unterpaket einen separaten Befehl darstellt. Der Einstiegspunkt befindet sich in der Datei cmd/go/main.go:

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,
    }
}

Hier finden Sie alle Go-Unterbefehle und deren Hilfsdokumentationen.

bug

sh
$ go help bug
usage: go bug

Bug opens the default browser and starts a new bug report.
The report includes useful system information.

Dieser Befehl hat keine Parameter oder Flags. Er öffnet Ihren Standardbrowser und ruft die Issue-Seite des github.com/golang/go-Repositories auf, um Ihnen das Melden von Fehlern zu erleichtern. Darüber hinaus hat er keine weitere Funktion.

version

Mit dem version-Befehl können Sie die aktuelle Go-Versionsinformation anzeigen.

go
$ go version -h
usage: go version [-m] [-v] [file ...]

Ohne Parameter gibt er die aktuelle Go-Sprachversion aus:

sh
$ go version
go version go1.21.0 windows/amd64

Er akzeptiert auch Dateipfade als Parameter und gibt die Go-Version aus, die beim Kompilieren aller erkennbaren Binärdateien in diesem Pfad verwendet wurde.

sh
$ 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.0

Das -v-Flag weist den version-Befehl an, die Go-Version von nicht erkennbaren Dateien auszugeben. Das -m-Flag gibt Modulinformationen und einige Kompilierungsparameter der Binärdatei aus. Hier ein einfaches Beispiel:

sh
$ 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=v1

go selbst ist eine Binärdatei. Tatsächlich gibt go version ohne Parameter die Go-Sprachversion seiner eigenen Binärdatei aus, da alle Toolchains von cmd/go von der Go-Sprache selbst implementiert werden.

env

Mit dem env-Befehl können Sie alle Go-Umgebungsvariablen anzeigen. Das Ändern dieser Umgebungsvariablen beeinflusst das Verhalten der Go-Toolchain.

sh
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.

Ohne Parameter gibt der Befehl die Werte aller Go-Umgebungsvariablen aus:

sh
$ go env
set GO111MODULE=on
set GOARCH=amd64
...

Wenn Sie den Namen einer Umgebungsvariable als Parameter angeben, wird nur der Wert dieser Variable ausgegeben:

sh
$ go env GO111MODULE
on

Mit -json wird die JSON-Form ausgegeben:

sh
$ go env -json
{
        "AR": "ar",
        "CC": "gcc",
    ......
}

Mit dem -w-Flag und dem Parameter im Format var=value wird der Wert einer Variable dauerhaft geändert:

sh
$ go env -w GO111MODULE=on

Mit dem -u-Flag können Sie eine Variable auf den Standardwert zurücksetzen:

sh
$ go env -u GO111MODULE

Mit go help environment können Sie die Beschreibung jeder Umgebungsvariable anzeigen:

sh
$ 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.
    ......

Im Folgenden werden einige häufig verwendete Umgebungsvariablen vorgestellt:

GOVERSION

Der Wert dieser Umgebungsvariable hängt von der Go-Sprachversion ab, die in der Datei $GOROOT/VERSION gespeichert ist. Diese Datei enthält die aktuelle Go-Version und Build-Zeit.

sh
$ cat $GOROOT/VERSION
go1.21.3
time 2023-10-09T17:04:35Z

Der Wert der runtime.Version-Variable ist identisch mit GOVERSION, und diese Umgebungsvariable kann nicht geändert werden.

GOENV

Im $GOROOT-Verzeichnis befindet sich eine Standard-Konfigurationsdatei namens go.env:

sh
$ 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=auto

Das Format ist einfach key=value. Die mit go env -w key=value geänderten Umgebungsvariablen werden in die Konfigurationsdatei geschrieben. Sie können jedoch auch eine benutzerdefinierte Konfigurationsdatei verwenden. Die GOENV-Umgebungsvariable kann den Pfad der env-Konfigurationsdatei manuell festlegen. Der Wert der GOENV-Umgebungsvariable kann nur durch Betriebssystem-Umgebungsvariablen überschrieben werden, nicht durch den go env -w-Befehl.

GOHOSTARCH

Repräsentiert die CPU-Architektur des lokalen Rechners. Dient nur zur Anzeige. Der Wert dieser Umgebungsvariable wird nicht aus der Konfigurationsdatei gelesen und kann nicht geändert werden.

GOHOSTOS

Repräsentiert das Betriebssystem des lokalen Rechners. Dient nur zur Anzeige. Der Wert dieser Umgebungsvariable wird nicht aus der Konfigurationsdatei gelesen und kann nicht geändert werden.

GOOS

Beim Kompilieren bestimmt der Wert von GOOS, für welches Zielsystem die Binärdatei kompiliert wird. Der Standardwert ist GOHOSTOS, also das lokale Betriebssystem. Es gibt folgende Optionen:

  • linux
  • darwin
  • windows
  • netbsd
  • aix
  • android

Tatsächlich werden mehr Betriebssysteme unterstützt. Verwenden Sie den Befehl go tool dist list, um alle unterstützten Werte anzuzeigen:

sh
$ 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
windows

GOARCH

Beim Kompilieren bestimmt der Wert von GOARCH, welche CPU-Architektur-Anweisungen beim Kompilieren verwendet werden. Der Standardwert ist GOHOSTARCH, also die lokale CPU-Architektur. Es gibt folgende Optionen:

  • amd64
  • 386
  • arm
  • ppc64

Tatsächlich werden mehr Architekturen unterstützt. Verwenden Sie den Befehl go tool dist list, um alle unterstützten Werte anzuzeigen:

sh
$ go tool dist list | awk -F '/' '{print $2}' | awk '!seen[$0]++'
ppc64
386
amd64
arm
arm64
riscv64
wasm
loong64
mips
mips64
mips64le
mipsle
ppc64le
s390x

Beachten Sie, dass GOOS und GOARCH nicht beliebig kombiniert werden können. Einige Betriebssysteme unterstützen nur bestimmte CPU-Architekturen.

GOROOT

GOROOT repräsentiert das Stammverzeichnis der Go-Installation. Der Wert von GOROOT kann nicht direkt geändert werden und kann nur durch Betriebssystem-Umgebungsvariablen überschrieben werden.

sh
$ ls $GOROOT -1
api
bin
codereview.cfg
CONTRIBUTING.md
doc
go.env
lib
LICENSE
misc
PATENTS
pkg
README.md
SECURITY.md
src
test
VERSION

Im Stammverzeichnis befinden sich mehrere wichtige Ordner oder Dateien:

  • lib: Enthält einige Abhängigkeiten. Derzeit nur eine Bibliothek mit Zeitzoneninformationen verschiedener Länder, gespeichert in $GOROOT/lib/time. Kompilierte Binärdateien enthalten diese Zeitzoneninformationen nicht.

  • pkg: Enthält einige Tool-Bibliotheken und Header-Dateien. Zum Beispiel sucht der Befehl go tool im Verzeichnis $GOROOT/pkg/tool nach den Binärdateien der Go-Toolchain.

  • bin: Enthält Binärdateien. Standardmäßig nur die ausführbaren Dateien go und gofmt. $GOROOT/bin sollte zum System-Pfad hinzugefügt werden, andernfalls können Go-Befehle nicht verwendet werden.

  • src: Enthält Go-Quellcode

  • VERSION: Diese Datei enthält Versionsinformationen der Go-Sprache.

  • go.env: Dies ist die Standard-env-Konfigurationsdatei.

GOPATH

Der Standardwert von GOPATH ist $HOME/go. Der Wert dieser Umgebungsvariable gibt an, wo importierte Dateien bei der Auflösung von import-Anweisungen gesucht werden. In der frühen Zeit vor gomod wurde GOPATH speziell zum Speichern verschiedener Drittanbieter-Bibliotheken verwendet. Die Struktur ist wie folgt:

sh
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)

Nach der Einführung von gomod dient GOPATH nur noch zum Speichern von mit go get heruntergeladenen Abhängigkeiten sowie zum Speichern von mit go install heruntergeladenen und kompilierten Binärdateien. Beachten Sie, dass der Speicherort von GOPATH nicht mit GOROOT identisch sein darf, andernfalls hat er keine Wirkung.

sh
$ go env GOBIN
warning: GOPATH set to GOROOT (/home/user/go) has no effect

Zum Zeitpunkt der Erstellung dieses Artikels ist die Go-Sprachversion bereits bei go1.21.3 angekommen. Abgesehen von sehr alten Projekten verwendet praktisch niemand mehr gopath zur Abhängigkeitsverwaltung.

GOBIN

GOBIN dient zum Speichern von Drittanbieter-Binärdateien, die mit go install heruntergeladen und kompiliert wurden. Der Standardwert ist $GOPATH/bin. Wie $GOROOT/bin sollte auch dieses Verzeichnis zum Betriebssystem-Pfad hinzugefügt werden, andernfalls können die Binärdateien im GOBIN-Verzeichnis nicht verwendet werden.

GOMODCACHE

GOMODCACHE gibt den Speicherort für mit go get heruntergeladene Abhängigkeiten an. Der Standardwert ist $GOPATH/pkg/mod. Das Speicherformat ist wie folgt:

$GOMODCACHE/domain/username/project@verion

Auf derselben Ebene befindet sich ein Ordner namens sumdb, der Informationen zur Abhängigkeitsprüfsummen-Datenbank enthält.

GOCACHE

Speichert Cache-Informationen für die Kompilierung. Der Standardwert ist $HOME/.cache/go-build. In diesem Verzeichnis wird eine README-Datei generiert.

sh
$ 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.

Jeder build-Vorgang erzeugt viele Dateien. Go cached diese Dateien, um sie bei der nächsten Kompilierung wiederzuverwenden.

GOTEMPDIR

Dient zum Speichern temporärer Dateien, die während der Kompilierung entstehen, z. B. temporäre Binärdateien für go run. Der Standardwert ist das vom Betriebssystem angegebene temporäre Verzeichnis. Unter macOS oder Linux ist es /tmp, unter Windows %TEMP%. Es kann auch auf einen benutzerdefinierten Speicherort geändert werden.

GO111MODULE

Diese Umgebungsvariable bestimmt, welche Methode zur Verwaltung von Go-Projektabhängigkeiten verwendet wird. Es gibt drei verfügbare Werte:

  • off: Deaktiviert gomod, verwendet gopath und ignoriert alle go.mod-Dateien.
  • on: Verwendet gomod, nicht gopath (Standard).
  • auto: Automatische Erkennung. Wenn die Projektdatei eine go.mod-Datei enthält, wird gomod zur Verwaltung verwendet.

TIP

Warum heißt es GO111MODULE und nicht einfach GOMODULE? Weil gomod erstmals in Go-Version 1.11 eingeführt wurde.

GOPROXY

Go-Modul-Proxy. Der Standardwert ist https://proxy.golang.org,direct. URLs werden durch Kommas getrennt. direct bedeutet, dass der Modul-Proxy direkt übersprungen und VCS verwendet wird. Letzteres wird nur ausgeführt, wenn ersteres nicht zugänglich ist. Eine weitere verfügbare Option ist off, die das Herunterladen von Modulen verbietet. Darüber hinaus kann GOPROXY auch eine Dateiadresse sein, zum Beispiel:

GOPROXY=file://$(go env GOMODCACHE)/cache/download

Mit go get -x können Sie die während des Abhängigkeits-Download-Prozesses ausgeführten Befehle anzeigen und so feststellen, ob ein Proxy verwendet wird.

sh
$ 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.1

Die Verwendung eines Modul-Proxys kann die Download-Geschwindigkeit von Modulen effektiv verbessern. Benutzer in China können standardmäßig den offiziellen Proxy nicht ohne Proxy-Zugriff访问. Derzeit sind folgende öffentliche und vertrauenswürdige Drittanbieter-Modul-Proxys verfügbar:

  • https://proxy.golang.com.cn: Open Source und bietet Enterprise-Dienste
  • https://goproxy.cn: Bereitgestellt und Open Source von Qiniu Cloud

Es gibt auch Open-Source-Lösungen für selbst gehostete Modul-Proxys: goproxy

GOSUMDB

GOSUMDB wird verwendet, um die Adresse der Prüfsummen-Datenbank für Abhängigkeitsbibliotheken festzulegen. Standardmäßig ist es sum.golang.org. Wenn Sie einen Proxy eingestellt haben,访问 Go über den Proxy auf die Prüfdatenbank zu.

GOPRIVATE

Die GOPRIVATE-Umgebungsvariable wird verwendet, um private Repositories festzulegen. Übereinstimmende Repositories werden nicht über sumdb überprüft und verwenden keinen Proxy, sondern laden Abhängigkeiten direkt über VCS herunter. Es unterstützt Wildcard-Einstellungen, getrennt durch Kommas. Wie unten gezeigt, werden alle Abhängigkeiten mit dem Suffix corp.example.com und名为github.com/gohper/myproject keinen Proxy und sumdb verwenden.

GOPRIVATE=*.corp.example.com,github.com/gohper/myproject

Sie können auch einen bestimmten Benutzer oder eine Organisation festlegen:

GOPRIVATE=github.com/gopher,github.com/myorganization

GONOPROXY

Gibt an, welche Abhängigkeiten keinen Proxy verwenden sollten. Die Regeln sind mit GOPRIVATE identisch und überschreiben GOPRIVATE.

GONOSUMDB

Gibt an, welche Abhängigkeiten keine Prüfdatenbank verwenden sollten. Die Regeln sind mit GOPRIVATE identisch und überschreiben GOPRIVATE.

GOINSECURE

Gibt an, welche Abhängigkeiten direkt über VCS heruntergeladen werden sollen. Die Regeln sind mit GOPRIVATE identisch und werden von GONOPROXY und GONOSUMDB überschrieben.

GOVCS

Legt das Versionskontrollsystem für die Modulverwaltung fest. Standardmäßig public:git|hg,private:all. Sie können auch VCS für bestimmte Domains einschränken, zum Beispiel:

GOVCS=github.com:git,evil.com:off,*:git|hg

In den obigen Einschränkungen kann github nur git verwenden, evil.com ist nicht erlaubt. Verwenden Sie |, um mehrere VCS anzugeben. Wenn Sie keine Einschränkungen vornehmen möchten, können Sie Folgendes einstellen:

GOVCS=*:all

Wenn Sie die Verwendung von VCS nicht允许 möchten, können Sie Folgendes einstellen:

GOVCS=*:off

GOWORK

Legt fest, ob der Workspace aktiviert ist. Standardmäßig leer, d. h. aktiviert. Wenn auf off gesetzt, wird deaktiviert und alle go.work-Dateien werden ignoriert.

GOTOOLDIR

Legt den Speicherort der zu verwendenden Go-Toolchain fest. Standardmäßig $GOROOT/pkg/tool, wo auch die Standard-Toolchain gespeichert ist.

GODEBUG

Legt Debug-Optionen fest, um das Ausführungsverhalten bestimmter Teile von Go-Programmen über Schlüssel-Wert-Paare zu steuern, zum Beispiel:

GODEBUG=http2client=0,http2server=0

Diese Einstellungen dienen dazu, bei Inkompatibilitäten während Versionsaktualisierungen ein Zurücksetzen auf das alte Verhalten zu ermöglichen. Zum Beispiel允许 panic(nil) in Version 1.21 nicht mehr. Dafür hat das Go-Team offiziell GODEBUG History dokumentiert. Weitere Details finden Sie unter GODEBUG.

CGO_ENABLED

Gibt an, ob cgo aktiviert ist. Standardmäßig 1, d. h. aktiviert. Auf 0 setzen, um es zu deaktivieren.

Die oben genannten Umgebungsvariablen sind die häufig verwendeten. Für weniger häufig verwendete wie CGO, WASM usw. wird hier nicht weiter eingegangen. Bei Interesse können Sie sich selbst informieren.

build

Go unterstützt zwei Compiler: gccgo und gc. gcc ist ein alter C/C++-Compiler, der mehrere Sprachen einschließlich Go unterstützt. Letzterer, gc, steht nicht für Garbage Collection, sondern für Go Compiler. Go wurde in Version 1.5 selbst kompiliert. gc ist ein vollständig in Go geschriebener Compiler, dessen Quellcode sich im cmd/compile-Paket befindet. Da er vollständig in Go implementiert ist, ist es sehr bequem, die internen Mechanismen zu verstehen und zu lernen. Standardmäßig verwendet der Compiler gc. Übrigens gibt es auch zwei Go-Debugger: gdb und dlv. Ersterer ist ein alter C/C++-Debugger, der mehrere Sprachen einschließlich Go unterstützt. Letzterer ist ein in Go geschriebener Debugger, der Go besser unterstützt. Er ist ebenfalls Open Source und wird empfohlen.

Der build-Befehl kompiliert Go-Quelldateien zu ausführbaren Binärdateien. Sie werden ein sehr schnelles Kompilierungserlebnis erleben, was eine der Eigenschaften von Go ist.

sh
$ go build -h
usage: go build [-o output] [build flags] [packages]
Run 'go help build' for details.

Er akzeptiert drei Parameter: den mit -o angegebenen Dateiausgabepfad, Build-Flags zur Steuerung des Kompilierungsverhaltens und zuletzt das zu kompilierende Paket. Dieser Parameter muss am Ende stehen. Hier ein einfaches Beispiel ohne Build-Flags:

sh
# Windows
$ go build -o .\bin\golearn.exe golearn

# macOS / Linux
$ go build -o ./bin/golearn golearn

./bin/golearn.exe ist der Ausgabepfad, golearn ist das zu kompilierende Modul. Es kann auch eine Hauptdatei oder ein Ordner sein. Zum Beispiel wird im folgenden einfachen Beispiel main.go als Kompilierungsziel verwendet:

sh
# Windows
$ go build -o .\bin\golearn.exe main.go

# macOS / Linux
$ go build -o ./bin/golearn main.go

Beim Kompilieren werden alle Dateien, die auf _test.go enden, ignoriert, da es sich vereinbarungsgemäß um Testdateien handelt.

Darüber hinaus unterstützt der build-Befehl zahlreiche Build-Flags zur Steuerung des Kompilierungsverhaltens.

  • -x: Detaillierte Anweisungen während des Kompilierungsprozesses ausgeben
  • -n: Ähnlich wie -x, gibt aber nur die Anweisungen aus, ohne sie tatsächlich auszuführen.
  • -v: Kompilierte Pakete ausgeben
  • -p: Parallelität während des Kompilierungsprozesses
  • -a: Erzwingt erneutes Kompilieren, auch wenn bereits aktuell.
  • -compiler: Welcher Compiler verwendet werden soll, gccgo oder gc. Letzterer ist der in Go geschriebene Compiler.
  • -race: Race-Detection aktivieren
  • -msan: Speicheranalyse aktivieren
  • -asan: Adressanalyse aktivieren
  • -cover: Code-Coverage-Detection aktivieren
  • -buildmode: Kompilierungsmodus angeben. Optionen: archive, c-archive, c-shared, default, shared, exe, pie, plugin.
  • -pgo: PGO-Datei angeben
  • -trimpath: Quellcode-Pfadpräfixe entfernen. Zum Beispiel wird aus dem relativen Pfad /var/lib/go/src/main.go nach dem Entfernen nur der relative Pfad /main.go zur Modul-Pfad. Nach Aktivierung dieser Option steigt die Kompilierungszeit deutlich, etwa 20-40%, abhängig von der Anzahl der Dateien.
  • -toolexec: Vor der Kompilierung auszuführende Go-Befehle. Format: -toolexec 'cmd args'.
  • -gcflags: Bestimmte Tags für den gc-Compiler angeben
  • -gccgoflags: Bestimmte Tags für den gccgo-Compiler angeben
  • -ldflags: Bestimmte Tags für das Link-Tool angeben

Für Parameter wie ldflags können Sie -help übergeben, um mögliche Werte anzuzeigen, zum Beispiel:

sh
$ 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
......

Die oben genannten sind die häufig verwendeten. Für andere weniger häufig verwendete können Sie sich selbst informieren.

gcflags

Mit gcflags können Sie Parameter an den gc-Compiler übergeben, um bestimmtes Verhalten zu steuern. Das Format ist -gcflags="pattern=args list", wobei args list die Parameterliste ist und pattern den Wirkungsbereich angibt. Es gibt folgende verfügbare Werte:

  • main: Top-Level-Paketpfad der Hauptdatei
  • all: Aktuelles Modul und alle Abhängigkeiten im aktuellen Modus
  • std: Standardbibliothek
  • cmd: Alle Quelldateien im cmd-Paket
  • Wildcards, z. B. ., ./..., cmd/....

Diese pattern-Regel gilt für alle Flags, die dieses Format unterstützen, z. B. ldflags. Mit folgendem Befehl können Sie verfügbare Parameter anzeigen:

sh
$ go build -gcflags -help
usage: compile [options] file.go...
  -%    debug non-static initializers
  -+    compile runtime
  -B    disable bounds checking
  -C    disable printing of column numbers in error messages
  -D path
        set relative path for local imports
  -E    debug symbol export
  -I directory
        add directory to import search path
  -K    debug missing line numbers
  -L    show actual source file name for error locations affected by //line directives
  -N    disable optimizations
  -S    print assembly listing
  -V    print version and exit
  -W    debug parse tree after type checking
  ......

Im Folgenden werden einige häufig verwendete Parameter vorgestellt:

  • -S: Gibt die Assembly-Form des Codes aus
  • -N: Deaktiviert Kompilierungsoptimierungen
  • -m: Gibt Optimierungsentscheidungen aus
  • -l: Deaktiviert Funktions-Inlining
  • -c: Parallelität der Kompilierung
  • -dwarf: DWARF-Symbole generieren

Wenn Sie beispielsweise die Assembly-Form des Codes anzeigen möchten, können Sie den -S-Parameter verwenden und Optimierungen und Inlining deaktivieren, um die ursprüngliche Form wiederherzustellen:

sh
$ 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

Mit ldflags können Sie Parameter an den Linker übergeben, um bestimmtes Verhalten zu steuern. Mit folgendem Befehl können Sie alle verfügbaren Werte für ldflags anzeigen, fast 20-30 Stück:

sh
$ 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)
  .....

Der -X-Parameter von ldflags ist eine sehr praktische Funktion. Er ermöglicht das Definieren von String-Variablenwerten指定 Pakets während des Linkens. Mit dieser Funktion können wir bequem Metainformationen zur Kompilierungszeit injizieren. Da es sich nur um eine Variable handelt, ist sie auch zur Laufzeit leicht abrufbar. Hier ein einfaches Beispiel:

go
package main

import "fmt"

var (
  Version string
)

func main() {
  fmt.Println(Version)
}

Befehl ausführen:

sh
go build -ldflags "-X main.Version=$(git describe --always)" main.go

Nach dem Ausführen wird die SHA1-Prüfsumme des Git-Commits ausgegeben:

5e3fd7a

Weitere praktische Parameter sind:

  • -w: Generiert kein DWARF, was Informationen zur Quellcode-Debugging erleichtert.
  • -s: Deaktiviert die Symboltabelle

Diese beiden werden normalerweise zusammen verwendet und können die Größe der kompilierten Binärdatei erheblich reduzieren, etwa 40%-50%. Der Nachteil ist jedoch offensichtlich: Debugging ist nicht möglich. Hier ein Beispiel:

sh
$ go build -ldflags="-w -s" main.go

Cross-Kompilierung

Die Go-Kompilierung hat zwei Hauptmerkmale: Erstens schnell, zweitens Cross-Kompilierung. Cross-Kompilierung bedeutet, dass Sie lokal Zielcode für andere Systeme kompilieren können, z. B. auf windows Binärdateien für linux oder darwin kompilieren und umgekehrt. Viele Sprachen unterstützen Cross-Kompilierung, was nichts Besonderes ist. Aber Go macht Cross-Kompilierung sehr einfach, nur in zwei Schritten:

  1. Umgebungsvariable GOOS setzen, um das Zielbetriebssystem auszuwählen
  2. Umgebungsvariable GOARCH setzen, um die Ziel-CPU-Architektur auszuwählen
  3. Wie gewohnt go build zur Kompilierung verwenden

Der gesamte Prozess ist sehr kurz, erfordert keine zusätzlichen Tools oder Konfigurationen, und die Geschwindigkeit ist wie gewohnt schnell. Wie unten gezeigt:

makefile
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_win

Der erste Schritt SET CGO_ENABLED=0 deaktiviert cgo. Sobald Ihr Code cgo verwendet, kann Cross-Kompilierung nicht normal verwendet werden. Der zweite Schritt SET GOOS legt das Zielsystem fest. Optionen sind linux, darwin, windows, netbsd. Der dritte Schritt legt die CPU-Architektur fest, SET GOARCH. Optionen sind amd64, 386, arm, ppc64. Der letzte Schritt ist die Kompilierung wie gewohnt.

Kompilierungssteuerung

Der build-Befehl kann mit tags das Kompilierungsverhalten steuern. Es handelt sich um eine Art Anweisung im Quellcode. Sehen Sie sich ein Beispiel an, die Datei product.go:

go
// +build product

package main

import "fmt"

func main() {
  fmt.Println("product")
}

Die Datei debug.go:

go
// +build debug

package main

import "fmt"

func main() {
  fmt.Println("debug")
}

Beide haben eine // +build-Anweisung, die angibt, unter welchen Bedingungen sie kompiliert werden. Das Grundformat lautet:

go
// +build tag1 tag2

package pkg_name

Es gibt mehrere zu befolgende Regeln:

  1. Zwischen // und +build muss ein Leerzeichen sein.
  2. Sie muss über der Paketdeklaration stehen.
  3. Es muss eine leere Zeile zwischen ihr und der Paketdeklaration sein.

Darüber hinaus kann sie durch einfache Abstände logisch gesteuert werden: Leerzeichen bedeutet OR, Komma bedeutet AND, ! bedeutet NOT. Zum Beispiel:

go
// +build windows linux

package pkg_name

Bedeutet, dass die aktuelle Datei unter Windows oder Linux kompiliert wird.

go
// +build windows,amd64,!cgo linux,i386,cgo

package pkg_name

Dieses Beispiel bedeutet, dass sie nur kompiliert wird, wenn es sich um die Windows-Plattform mit amd64-Architektur und cgo nicht aktiviert ist, ODER die Linux-Plattform mit i386-Architektur und cgo aktiviert ist. Wenn Sie einfach nur möchten, dass eine Datei nicht kompiliert wird, können Sie ignore verwenden:

go
// +build ignore

package pkg_name

Es können auch mehrere Zeilen von Anweisungen existieren:

go
// +build windows
// +build amd64

package pkg_name

Mehrzeilige Anweisungen werden mit AND verarbeitet. Für Plattformen und Architekturen werden diese Tags beim Kompilieren automatisch von Go übergeben. Wir können auch benutzerdefinierte Tags übergeben. Nehmen wir die beiden Dateien vom Anfang als Beispiel:

sh
$ go build -tags="debug" . && ./golearn.exe
debug

$ go build -tags="product" . && ./golearn.exe
product

Wie Sie sehen können, ergibt die Ausgabe bei verschiedenen Tags unterschiedliche Ergebnisse. Damit ist das Ziel der Kompilierungssteuerung erreicht.

run

Sowohl der run-Befehl als auch build kompilieren den Quellcode. Der Unterschied besteht darin, dass der run-Befehl nach der Kompilierung direkt ausführt. Um die Kompilierungsgeschwindigkeit zu beschleunigen, generiert der run-Befehl während des Kompilierungsprozesses keine Debug-Informationen, unterstützt also kein Debugging. Außerdem wird nur eine temporäre Binärdatei generiert, die normalerweise im GOTMEPDIR-Verzeichnis gespeichert wird, z. B. /temp/go-build2822241271/b001/exe/main.exe.

sh
$ go run -h
usage: go run [build flags] [-exec xprog] package [arguments...]
Run 'go help run' for details.

Er unterstützt auch die Build-Flags des build-Befehls und bietet einen Parameter -exec, um anzugeben, welches Programm die Binärdatei ausführen soll. [arguments...] bezieht sich auf die Laufzeitparameter des Programms. Hier ein Beispiel:

go
package main

import (
  "fmt"
  "os"
)

var (
  Version string
)

func main() {
  fmt.Println(Version)
  fmt.Println(os.Args[1:])
}

Mit go run ausführen:

sh
$ go run -ldflags="-X main.Version=$(git describe --always)" main.go hello
5e3fd7a
[hello]

Insgesamt unterscheidet sich die Verwendung nicht wesentlich von go build, daher wird hier nicht weiter darauf eingegangen.

tool

Der tool-Befehl selbst hat keine Funktion. Seine Aufgabe ist es, Tools im cmd/-Verzeichnis direkt aufzurufen. Zum Beispiel ist cmd/compile der mitgelieferte Compiler. Mit go tool können Sie diese Tools direkt aufrufen, ohne die Binärdateien dieser Tools manuell ausführen zu müssen.

sh
$ go tool -h
usage: go tool [-n] command [args...]

Verwenden Sie den -n-Parameter, um alle unterstützten Befehlsparameter auszugeben:

sh
$ go tool -n
addr2line
asm
buildid
cgo
compile
covdata
cover
doc
fix
link
nm
objdump
pack
pprof
test2json
trace
vet

Diese Tools befinden sich im GOROOT/pkg/tool-Verzeichnis und sind nach Betriebssystem und CPU-Architektur gruppiert:

sh
$ 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*

Verwenden Sie das Format go doc cmd/command, um die Verwendung jedes Befehls anzuzeigen, zum Beispiel:

sh
$ 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.
...

Die vom cmd/compile unterstützten Flag-Parameter sind die zuvor erwähnten gcflags-Parameter. Der Unterschied zwischen go tool compile und go build besteht darin, dass ersterer nur für die Kompilierung verantwortlich ist und nur Dateien als Parameter akzeptiert. Letzterer kann Ordner, Pakete und Dateien als Parameter akzeptieren und führt nicht nur die Kompilierung des Quellcodes durch, sondern ist auch für das Verknüpfen von Dateien, das Entfernen unnötiger Dateien usw. verantwortlich. Ersterer ist ein Teil von Letzterem. Wir können die während des build-Prozesses ausgeführten Befehle ausgeben:

sh
$ 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
...

Während des Prozesses können Sie sehen, dass /golang/pkg/tool/windows_amd64/compile.exe aufgerufen wurde, was den Compiler aufruft. Neben compile gibt es viele weitere Tools, die aufgerufen werden können. Viele Go-Befehle sind tatsächlich nur Aliase für sie.

clean

Der clean-Befehl dient zum Entfernen von während des Kompilierungsprozesses generierten Objektdateien:

sh
$ go clean -h
usage: go clean [clean flags] [build flags] [packages]
Run 'go help clean' for details.

Er unterstützt folgende Flags:

  • -i: Entfernt die entsprechende Archiv- oder Binärdatei
  • -n: Gibt die während des Bereinigungsprozesses auszuführenden Befehle aus, führt sie aber nicht tatsächlich aus
  • -x: Gibt die während des Bereinigungsprozesses auszuführenden Befehle aus und führt sie aus
  • -r: Entfernt rekursiv über import path
  • -cache: Entfernt allen von go build generierten Cache
  • -testcache: Entfernt allen generierten Test-Cache
  • -modcache: Entfernt allen heruntergeladenen Modul-Cache
  • -fuzzcache: Entfernt den von fuzz test generierten Cache.

Bei Verwendung von go tool compile wird der Compiler-Befehl direkt aufgerufen, ohne dass go build viele Nachbereitungen durchführt, was Objektdateien erzeugt. Zum Beispiel erzeugt die Ausführung des folgenden Befehls:

sh
go tool compile -N -S -l main.go

eine Datei namens main.o. Verwenden Sie den go clean-Befehl, um sie zu entfernen. Oder verwenden Sie den -n-Parameter, um die auszuführenden Befehle auszugeben:

sh
$ 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.exe

Kompilierungs-Cache entfernen. Es löscht den im GOCACHE-Verzeichnis generierten Kompilierungs-Cache:

sh
$ go clean -cache -n
rm -r /cache/00 /cache/01 /cache/02

Entfernt den von fuzz test generierten Cache. Diese Caches werden standardmäßig im GOCACHE/fuzz/-Verzeichnis gespeichert:

sh
$ go clean -fuzzcache -n
rm -rf /cache/fuzz

fix

Zum Zeitpunkt der Erstellung dieses Artikels existiert die Go-Sprache seit zehn Jahren. Während des kontinuierlichen Updates und Änderns der Sprache können Inkompatibilitäten aufgrund von API-Änderungen auftreten. Der fix-Befehl wurde dafür entwickelt. Er erkennt veraltete APIs in Quelldateien und ersetzt sie durch neue APIs.

sh
$ go fix -h
usage: go fix [-fix list] [packages]
Run 'go help fix' for details.

Er unterstützt Ordner, Dateinamen und Verzeichnisse als Parameter. Er akzeptiert das -fix-Flag, um Parameter zu übergeben und anzugeben, welche Änderungen vorgenommen werden sollen. Verfügbare Werte können mit dem Befehl go tool fix -help angezeigt werden:

sh
$ 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.

Hier ein Beispiel: Der Quellcode verwendet das Paket golang.org/x/net/context:

sh
package main

import (
  "fmt"
  "golang.org/x/net/context"
)

func main() {
  background := context.Background()
  fmt.Println(background.Err())
}

Mit go fix korrigieren, um es durch das context-Paket der Standardbibliothek zu ersetzen. Wir können den folgenden Befehl verwenden:

sh
$ go fix -fix context main.go

Oder Sie können es nicht ersetzen und stattdessen die Dateiänderungen vorher/nachher anzeigen:

sh
$ 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() {

Go existiert seit über zehn Jahren und hat nur neun verfügbare Ersatzparameter, was zeigt, dass die Kompatibilität recht gut erhalten wurde.

fmt

Der fmt-Befehl ist das mitgelieferte Formatierungstool von Go zum Formatieren von Go-Quelldateien.

sh
$ go fmt -h
usage: go fmt [-n] [-x] [packages]
Run 'go help fmt' for details.

Mit dem Befehl go doc gofmt können Sie die detaillierte Dokumentation anzeigen:

sh
$ 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 verwendet Tab für Einrückungen und Leerzeichen für Ausrichtungen. Standardmäßig wird der formatierte Code in die Standardausgabe ausgegeben, nicht in die Originaldatei überschrieben. Der go fmt-Befehl verwendet tatsächlich den gofmt-Befehl, der eine eigenständige Binärdatei im GOROOT/bin-Verzeichnis ist:

sh
$ ls $GOROOT/bin -1
go.exe*
gofmt.exe*

Wenn Sie dem go fmt-Befehl das -n-Flag hinzufügen, können Sie die auszuführenden Anweisungen anzeigen:

sh
$ go fmt main.go
/golang/bin/gofmt.exe -l -w main.go

Wie Sie sehen können, ist go fmt eigentlich nur ein Alias für gofmt -l -w. Der gofmt-Befehl hat folgende Parameter:

  • -d: Gibt Unterschiede zwischen formatiertem und originalem Code aus
  • -e: Gibt alle Fehler aus
  • -l: Gibt den Namen der geänderten Dateien aus
  • -r: Wendet Formatierungsregeln an
  • -s: Versucht, Code zu vereinfachen
  • -w: Überschreibt die Quelldatei. Bei Fehlern wird das Backup wiederhergestellt.

Angenommen, es gibt folgende Quelldatei:

go
$ cat main.go
package main

import "fmt"

func main() {
fmt.Println("hello world!")}

Mit dem -d-Parameter können Sie die Änderungen im Voraus anzeigen:

sh
$ 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!")
+}

Der -l-Parameter gibt den Namen der zu ändernden Dateien aus:

$ gofmt -l .
main.go

Bei Syntaxfehlern gibt der -e-Parameter detailliertere Informationen aus:

sh
$ 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 wendet Änderungen auf die Quelldatei an:

sh
$ gofmt -l -w .
main.go

$ cat main.go
package main

import "fmt"

func main() {
        fmt.Println("hello world!")
}

Sie können feststellen, dass gofmt als Formatierungstool überhaupt keine benutzerdefinierte Konfiguration bietet. Im Gegensatz dazu bietet der Formatierer prettify für JS-Code viele Konfigurationen zur Code-Formatierung. Dies zeigt die Haltung der Go-Offiziellen: Keine Individualisierung, der Code-Stil aller sollte möglichst konsistent sein. Zumindest hat es den Vorteil, dass Sie beim Lesen von Code nicht die Gewohnheiten anderer anpassen müssen. Allerdings gibt es tatsächlich eine benutzerdefinierte Option: die Ersetzungsregeln für formatierten Code. Regeln können benutzerdefiniert werden, das Format lautet:

pattern -> replacement

Zum Beispiel redundante Klammern entfernen:

(a) -> a

Dateiänderungen anzeigen:

sh
$ 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!")
 }

Wie Sie sehen können, entfernt gofmt die redundanten Klammern.

get

Der get-Befehl ist absolut einer der am häufigsten verwendeten während der Go-Entwicklung. Seine Aufgabe ist es, den Quellcode指定 Pakets in das dem GOMODCACHE entsprechende Verzeichnis herunterzuladen.

sh
$ go get -h
usage: go get [-t] [-u] [-v] [build flags] [packages]
Run 'go help get' for details.
  • -u: Versucht, Neben- und Patch-Versionen des Pakets zu aktualisieren. Bei Hauptversionsänderungen wie v1->v2 wird nicht aktualisiert.
  • -t: Aktualisiert Abhängigkeitsversionen in Tests
  • -v: Gibt kompilierte Pakete aus. Tatsächlich einer der Parameter von build flags.

In früheren Zeiten war go get ähnlich wie go install. Es lud Pakete herunter und kompilierte sie. Mit der Entstehung und Verbesserung von Go-Modulen wurde diese Funktion allmählich eingestellt. Der get-Befehl wird jetzt am häufigsten zum Herunterladen und Auflösen von Abhängigkeiten für Go-Module verwendet. Daher können Sie sehen, dass der go get-Befehl auch build flags unterstützt. Wenn Sie versuchen, go get außerhalb eines Moduls wie go install zu verwenden, wird eine Warnung angezeigt, dass diese Verwendung veraltet ist:

sh
$ 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'.

Warum diese in der Dokumentation noch erwähnt werden, ist unbekannt. Wenn Sie den Quellcode des get-Befehls durchsehen, werden Sie feststellen, dass er die alten Flags noch enthält:

go
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
)

Zurück zum Thema: Der get-Befehl lädt den Quellcode指定 Pakets in das lokale globale Abhängigkeitsverzeichnis herunter, also das GOCACHE-Verzeichnis, und zeichnet die Informationen in den Dateien go.mod und go.sum auf. Erstere ist für die Versionsaufzeichnung verantwortlich, Letztere für die SHA1-Prüfsumme zur Sicherheit. get basiert tatsächlich auf VCS, also dem lokalen Versionskontrollsystem. Insgesamt werden folgende unterstützt:

  • git
  • hg (Mercurial)
  • bzr (Bazaar)
  • svn
  • fossil

Standardmäßig werden nur git und hg unterstützt. Kann in GOVCS konfiguriert werden, das Format lautet:

GOVCS=github.com:git,example.com:hg,*:git|hg,*:all

GOVCS unterstützt nur git und hg als VCS. Die anderen drei müssen in GOPRIVATE konfiguriert werden.

Der go get-Befehl hat folgende Verwendungsmöglichkeiten. Kann die Abhängigkeitsadresse direkt als Parameter verwenden:

sh
$ go get golang.org/x/net

Oder eine Version angeben:

sh
$ go get golang.org/x/net@0.17.0

Neueste Version angeben:

sh
$ go get golang.org/x/net@latest

Version aktualisieren versuchen:

sh
$ go get -u golang.org/x/net

Eine Abhängigkeit entfernen:

sh
$ go get golang.org/x/net@none

Die oben genannten dienen zur Verwaltung normaler Abhängigkeiten. Er kann auch weniger normale Abhängigkeiten verwalten, z. B. die Go-Sprachversion aktualisieren:

sh
$ 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.3

Kann sogar die Go-Toolchain-Version aktualisieren:

sh
$ go get toolchain@latest

Wenn Sie go get verwenden, um Go und die Toolchain-Version zu aktualisieren, installieren sie die neue Go-Version im GOMODCACHE/golang.org/-Verzeichnis:

sh
$ ls $(go env GOMODCACHE)/golang.org -1
'toolchain@v0.0.1-go1.21.3.windows-amd64'/
x/

Dann können Sie GOROOT manuell ändern, um zur指定 Version zu wechseln.

install

Der install-Befehl ist ähnlich wie der get-Befehl. Beide dienen zum Herunterladen von Drittanbieter-Abhängigkeiten. Der Unterschied besteht darin, dass get den Quellcode herunterlädt, während install den Quellcode zu einer für den lokalen Rechner ausführbaren Binärdatei kompiliert. Der Speicherpfad der Binärdatei ist zuerst im GOBIN-Verzeichnis, dann in GOPATH/bin. Die Hauptfunktion dieses Befehls ist das Herunterladen einiger öffentlicher CLI-Tools von Drittanbietern. Dank der Kompilierungsgeschwindigkeit und Portabilität von Go müssen keine Binärdateien heruntergeladen werden, sondern der Quellcode wird heruntergeladen und lokal kompiliert.

sh
$ go install -h
usage: go install [build flags] [packages]
Run 'go help install' for details.

Der install-Befehl akzeptiert Build-Flags und Paketnamen als Parameter. Bei aktiviertem gomod muss der Paketname eine Versionsnummer enthalten. Zum Beispiel den Delve-Debugger herunterladen:

sh
$ 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/

Zuerst wird der Quellcode in das GOMODCACHE-Verzeichnis heruntergeladen, was mit dem get-Befehl übereinstimmt. Dann wird in ein temporäres Arbeitsverzeichnis gewechselt, kompiliert, die Binärdatei in das GOPATH/bin-Verzeichnis verschoben und schließlich der temporäre Ordner gelöscht. Der install-Befehl hat eine Einschränkung: Das heruntergeladene Paket muss das Hauptpaket des Projekts sein, d. h. es muss eine main.go-Hauptdatei enthalten, andernfalls wird eine Fehlermeldung angezeigt, dass es nicht installiert werden kann. Zum Beispiel, Gin mit go install herunterladen:

sh
$ 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 package

Gin ist eine Web-Framework-Abhängigkeitsbibliothek, kein CLI-Tool, hat natürlich keine Hauptdatei, daher schlägt die Installation fehl.

list

Der list-Befehl listet Pakete指定 Positionen auf, eine pro Zeile, und unterstützt benutzerdefinierte formatierte Ausgabe. Er unterstützt viele Parameter. Voraussetzung für die Verwendung ist, dass er sich in einem gomod-unterstützenden Projekt befindet.

sh
$ go list -h
usage: go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
Run 'go help list' for details.

Er unterstützt folgende Parameter:

  • -f: Formatierungsparameter
  • -json: JSON-Format-Ausgabe
  • -compiled: Zeigt alle vom Compiler kompilierten Pakete an
  • -deps: Zeigt jeden Paketnamen und alle seine Abhängigkeiten an
  • -test: Zeigt das Testpaket jedes Pakets an
  • -e: Gibt bei fehlerhaften Paketen normal aus
  • -find: Löst die Abhängigkeiten dieser Pakete nicht auf
  • -export: Bei Verwendung dieses Parameters wird der Wert des Package.Export-Felds der Struktur auf die Datei gesetzt, die die neuesten Exportinformationen指定 Pakets enthält, und der Package.BuildID-Feldwert auf die BuildID des Pakets. Hauptsächlich für formatierte Ausgabe.

Modulinformationsparameter:

  • -m: Gibt Module statt Pakete aus

  • -versions: Zeigt alle verfügbaren Informationen eines Moduls an

  • -retracted: Zeigt zurückgezogene Versionen eines Moduls an

Der [packages]-Parameter kann ein指定 Paketname, ein Ordner oder all sein, was überall bedeutet. Bei Verwendung des -m-Parameters bedeutet all alle aktuellen Modulabhängigkeiten.

Zum Beispiel, aktuelle Datei hat nur eine main.go-Datei mit nur einer Ausgabe "hello world". Nach Ausführung von go list -deps . gibt es alle von diesem Projekt bis fmt und seinen Referenzen abhängigen Pakete aus:

bash
$ 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
golearn

Oder alle Modulabhängigkeiten des aktuellen Projekts ausgeben:

bash
$ 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

Die Ausgabe des list-Befehls ist zeilenbasiert, jede Zeile ist ein Paket. Die Offiziellen bieten den Parameter -f für benutzerdefinierte Zeilenausgabe. Der akzeptierte Wert ist die von der template/text-Template-Engine definierte Template-Syntax. Zum Beispiel:

sh
-f "package {{ .Dir }} {{ .Name }}"

Jedes iterierte Paket wird als folgende Struktur übergeben. Alle Felder dieser Struktur können als Template-Parameter verwendet werden:

go
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
}

Bei Iteration von Modulen wird folgende Struktur übergeben. Alle ihre Felder können ebenfalls als Template-Parameter verwendet werden:

go
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
}

Alle Pakete anzeigen:

bash
$ 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 tool

Module anzeigen:

bash
$ go list -m -f "mod {{.Path}} {{.Version}} {{.GoVersion}} {{.GoMod}}"
mod golearn  1.21.3 /golearn/go.mod

mod

go mod ist ein Befehl speziell zur Verwaltung von Go-Modulen.

sh
$ 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.

Es hat folgende Unterbefehle:

  • download: Lädt alle in der go.mod-Datei angegebenen Abhängigkeiten in den lokalen Cache herunter
  • edit: Bearbeitet die go.mod-Datei. Die bereitgestellte CLI-Schnittstelle ist hauptsächlich für andere Tools oder Skripte gedacht.
  • init: Initialisiert ein gomod-Projekt im aktuellen Verzeichnis
  • tidy: Lädt fehlende Abhängigkeiten herunter, entfernt ungenutzte Abhängigkeiten
  • graph: Gibt Abhängigkeitsdiagramm aus
  • verify: Überprüft lokale Abhängigkeiten
  • why: Erklärt, warum diese Module benötigt werden
  • vendor: Exportiert Projektabhängigkeiten in das vendor-Verzeichnis

init

sh
$ go help mod init
usage: go mod init [module-path]

Der init-Befehl dient zur Initialisierung eines gomod-Projekts. Der einzige Parameter ist der Modulpfad, der später als Grundlage dient, wenn andere Ihre Abhängigkeiten herunterladen möchten. Die Namenskonvention lautet im Allgemeinen:

domain_name/user_name/repo_name

Zum Beispiel, wenn die meisten Projekte auf github gehostet werden, könnte es sein:

github.com/jack/gotour

Es wird nicht empfohlen, spezielle Symbole als Modulpfad zu verwenden. Hier ein Anwendungsbeispiel:

sh
$ mkdir gotour

$ cd gotour

$ go mod init "github.com/jack/gotour"
go: creating new go.mod: module github.com/jack/gotour

tidy

$ go help mod tidy
usage: go mod tidy [-e] [-v] [-x] [-go=version] [-compat=version]

Der tidy-Befehl entfernt ungenutzte Abhängigkeitselemente aus go.mod, also nicht referenzierte Abhängigkeiten, und lädt referenzierte, aber nicht vorhandene Abhängigkeiten herunter. Er unterstützt folgende Parameter:

  • -v: Gibt gelöschte Modulabhängigkeiten aus
  • -e: Ignoriert Fehler während des Prozesses und fährt fort
  • -x: Gibt den Ausführungsprozess aus
  • -go=version: Aktualisiert die Go-Version in der go.mod-Datei
  • -compact=version: Behält alle zusätzlichen Prüfsummen bei, die von der angegebenen Haupt-Go-Version benötigt werden, um das Moduldiagramm erfolgreich zu laden. Wenn der go-Befehl dieser Version ein importiertes Paket aus einer anderen Modulversion lädt, führt tidy zu einem Fehler. Dieser Parameter wird im Allgemeinen selten verwendet und tritt normalerweise nur bei Versionsänderungen auf. Weitere Informationen finden Sie in dieser StackOverflow-Antwort: go modules - go mod tidy error message: "but go 1.16 would select" - Stack Overflow

Hier ein Anwendungsbeispiel:

sh
$ 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

sh
$ go help mod download
usage: go mod download [-x] [-json] [-reuse=old.json] [modules]

Obwohl der Name des download-Befehls als "Herunterladen" übersetzt wird, lädt er nur Abhängigkeiten in den lokalen Abhängigkeits-Cache herunter und ändert die go.mod-Datei nicht. Seine Funktion besteht darin, Abhängigkeiten im Voraus in den lokalen Dateicache herunterzuladen. Wenn Sie eine bestimmte Abhängigkeit herunterladen möchten, wird empfohlen, go get oder go mod tidy zu verwenden.

Hier einige Anwendungsbeispiele:

sh
$ 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)

Ohne Parameter lädt es alle im go.mod-Verzeichnis vorhandenen, aber nicht im lokalen Abhängigkeits-Cache vorhandenen Abhängigkeiten herunter. Wenn nichts herunterzuladen ist, gibt es aus:

go: no module dependencies to download

edit

sh
$ go help mod edit
usage: go mod edit [editing flags] [-fmt|-print|-json] [go.mod]

edit ist eine CLI-Schnittstelle zum Ändern der go.mod-Datei, die normalerweise von anderen Programmen verwendet wird. Einige Editor-IDEs verwenden diese Befehle, um gomod-Unterstützung bereitzustellen. Es unterstützt folgende Parameter:

  • -module: Ändert den Modulpfad
  • -go=version: Ändert die erwartete Go-Version
  • -require=path@version: Fügt eine Abhängigkeit hinzu
  • -droprequire=path@version: Entfernt eine Abhängigkeit
  • -exclude=path@version: Fügt eine ausgeschlossene Abhängigkeit hinzu
  • -dropexclude=path@version: Entfernt eine ausgeschlossene Abhängigkeit
  • -replace=old@version=new@version: Fügt eine ersetzende Abhängigkeit hinzu
  • -dropreplace=old@version: Entfernt eine ersetzende Abhängigkeit
  • -retract=version: Fügt einen Versionsrückzug hinzu
  • -dropretract=version: Entfernt einen Versionsrückzug

Weitere Parameter zur Anzeige:

  • -print: Gibt den Dateiinhalt aus
  • -json: Gibt im JSON-Format aus

Zum Beispiel:

$ 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

sh
$ go help mod graph
usage: go mod graph [-go=version] [-x]

Der graph-Befehl gibt das Abhängigkeitsdiagramm des aktuellen Projekts aus. Die Lesbarkeit ist schlecht und meist nicht für Menschen gedacht. Die Ergebnisse werden normalerweise verarbeitet und visuell dargestellt. Jede Zeile ist eine Abhängigkeit, das Format lautet:

引用方 被引用方

Zum Beispiel:

golearn go@1.21.3

Es unterstützt zwei Parameter:

  • -go=version: Lädt das Abhängigkeitsdiagramm mit der angegebenen Go-Version. Der Wert darf nicht kleiner als die Version in der go.mod-Datei sein.
  • -x: Zeigt die während des Prozesses ausgeführten Befehle.

Hier ein einfaches Anwendungsbeispiel:

sh
$ 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

sh
$ go help mod vendor
usage: go mod vendor [-e] [-v] [-o outdir]

Vendor war eine Alternative zu gopath vor der Einführung von gomod. Jedes Go-Projekt hatte ein vendor-Verzeichnis, das jede Projektabhängigkeit separat im Format domain/user/project speicherte, ähnlich wie das aufgeblähte node_module von Node.js, wo jede Projektabhängigkeit separat gespeichert wird. Diese Abhängigkeitsverwaltungsmethode erscheint heute tatsächlich ziemlich dumm, aber damals gab es keine bessere Lösung. Der Grund für die Beibehaltung von vendor ist, dass Go sein Abwärtskompatibilitätsversprechen einhält. Einige alte Projekte, einschließlich des Go-Quellcodes, verwenden möglicherweise noch vendor.

Zurück zum Thema: vendor ist ein Unterbefehl von go mod, der globale Abhängigkeiten, auf die das aktuelle Modul verweist, in das vendor-Verzeichnis exportieren kann.

sh
$ go mod vendor -h
usage: go mod vendor [-e] [-v] [-o outdir]
Run 'go help mod vendor' for details.

Es hat folgende Parameter:

  • -o: Gibt den Ausgabe-Pfadordner an
  • -v: Gibt jede Abhängigkeit aus
  • -e: Fährt bei Fehlern fort, ohne zu beenden

Hier ein Beispiel. Zuerst mit go list -m all die vom aktuellen Projekt referenzierten Abhängigkeiten anzeigen:

sh
$ 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.1

In das aktuelle vendor-Verzeichnis exportieren:

sh
$ 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.v3

Die exportierte Verzeichnisstruktur lautet wie folgt:

└─vendor
    ├─github.com
    │  ├─davecgh
    │  │  └─go-spew
    │  │      └─spew
    │  ├─pkg
    │  │  └─errors
    │  ├─pmezard
    │  │  └─go-difflib
    │  │      └─difflib
    │  └─stretchr
    │      └─testify
    │          └─assert
    └─gopkg.in
    |    └─yaml.v3
    |
    |--modules.txt

Die modules.txt darin ist die Datei, die alle Abhängigkeitselemente beschreibt, ähnlich wie die aktuelle go.mod.

verify

sh
$ go help mod verify
usage: go mod verify

Dieser Befehl überprüft, ob die Projektabhängigkeiten seit dem Herunterladen in den lokalen Speicher geändert wurden. Wenn kein Problem vorliegt, gibt er all modules verified aus:

sh
$ go mod verify
all modules verified

Andernfalls meldet er, wo Änderungen aufgetreten sind, und beendet den Befehl mit einem nicht normalen Status. Zum Beispiel:

sh
$ 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...

Erklärt, warum dieses Paket benötigt wird, gibt tatsächlich das Abhängigkeitsdiagramm darüber aus. Zum Beispiel:

sh
$ go mod why gorm.io/gorm
# gorm.io/gorm
golearn
gorm.io/gorm

Standardmäßig wird nur der Import von main analysiert. Mit dem -m-Parameter kann die Importsituation jedes Pakets analysiert werden.

work

Der Befehl work ist ein lokales Entwicklungstool für Go-Multi-Modul-Verwaltung.

bash
$ 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

Der Unterbefehl init dient zur Initialisierung eines Workspace. Dieser Befehl erstellt eine Datei namens go.work:

bash
$ go work init -h
usage: go work init [moddirs]
Run 'go help work init' for details.

Akzeptiert den Parameter [moddirs], um anzugeben, welche Module in die Verwaltung einbezogen werden sollen, zum Beispiel:

bash
$ go work init ./service ./api

use

Der Unterbefehl use dient zum Hinzufügen von Modulverzeichnissen zur Verwaltung in go.work:

bash
$ 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.

Akzeptiert [moddirs] als Parameter. Ein -r bedeutet, dass im [moddirs]-Pfad rekursiv nach Modulen gesucht wird, zum Beispiel:

bash
$ go work use -r ./oss-api ./multi_modules

edit

Die Funktion des Unterbefehls edit ist dieselbe wie bei go mod edit. Beide sind für CLI-Schnittstellen für andere Tools und Skripte gedacht.

$ 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 directories

Parameter sind wie folgt:

  • -fmt: Formatierung der go.work-Datei

  • -use, -dropuse: Hinzufügen und Entfernen von Modulpfaden

  • -replace=old[@v]=new[@v], -dropreplace=old[@v]=new[@v]: Zum Hinzufügen und Entfernen zu ersetzender Module

  • -go, -toolchain=name: Go-Version angeben und zu verwendende Toolchain angeben

  • -print: Gibt die letzten Änderungen aus, ohne in die Datei zurückzuschreiben

  • -json: Gibt im JSON-Format aus. Kann nicht mit -print gleichzeitig verwendet werden. Die entsprechende Typstruktur lautet wie folgt:

    go
    type 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
    }

Einige Anwendungsbeispiele sind wie folgt, formatierte Ausgabe:

bash
$ go work edit -fmt -print
go 1.22.0

use (
        ./ab/cd
        ./auth
        ./user
)

JSON-Ausgabe:

bash
$ go work edit -fmt -json
{
        "Go": "1.22.0",
        "Use": [
                {
                        "DiskPath": "./ab/cd"
                },
                {
                        "DiskPath": "./auth"
                },
                {
                        "DiskPath": "./user"
                }
        ],
        "Replace": null
}

sync

Der Unterbefehl sync dient zum Synchronisieren der Modulliste in go.work zurück zu den einzelnen Modulen im Workspace.

bash
$ go help work sync
usage: go work sync

Sync syncs the workspace's build list back to the
workspace's modules

Dieser Prozess findet hauptsächlich nach Abschluss der lokalen Entwicklung statt, wenn die einzelnen Module bereits veröffentlicht wurden. Zu diesem Zeitpunkt verwendet sync, um die go.mod-Dateien aller Module im Workspace basierend auf den Abhängigkeitsbeziehungen der einzelnen Module zu aktualisieren, sodass wir sie nicht manuell aktualisieren müssen.

vendor

Der vendor-Befehl erstellt eine Kopie aller von Modulen im Workspace abhängigen Bibliotheken im vendor-Verzeichnis.

bash
$ go work help vendor
usage: go work vendor [-e] [-v] [-o outdir]

Funktion wie go mod vendor, wird hier nicht weiter erläutert.

vet

Der Befehl vet ist ein statisches Fehlerprüfungstool für Go-Quellcode, ähnlich wie Lint-Tools in anderen Sprachen, z. B. Eslint.

sh
$ 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.

Zuerst ein einfaches Beispiel. Es gibt folgenden Quellcode:

sh
$ cat main.go
package main

import "fmt"

func main(){
        fmt.Println("hello world!"
}

Ohne Parameter im selben Verzeichnis go vet ausführen:

sh
$ go vet
vet: ./main.go:6:28: missing ',' before newline in argument list (and 1 more errors)

vet meldet, welche Datei, welche Zeile und welches Problem aufgetreten ist. Es unterstützt Build-Flags als Parameter, z. B. -n und -x, sowie Pakete, Ordner und Dateinamen als Parameter:

sh
$ go vet .
$ go vet main.go
$ go vet ./cmd
$ go vet runtime

Mit folgendem Befehl können Sie detailliertere Parameter und Erklärungen anzeigen:

sh
$ 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
    ......

Der Befehl go tool vet kann nicht direkt zur Code-Überprüfung verwendet werden. Sie sollten go vet verwenden. Die [vet flag]-Parameter von go vet unterstützen das Einstellen von Code-Analysegeräten. Verfügbare Werte sind:

asmdecl      Prüft, ob Assembler-Dateien nicht mit Go-Deklarationen übereinstimmen
assign       Prüft auf nutzlose Zuweisungen
atomic       Prüft auf häufige Fehler bei der Verwendung von sync/atomic
bools        Prüft auf häufige Fehler bei booleschen Operatoren
buildtag     Prüft //go:build und // +build Direktiven
cgocall      Prüft auf Verstöße gegen cgo-Zeigerübergaberegeln
composites   Prüft uninitialisierte zusammengesetzte Strukturen wie map, chan
copylocks    Prüft, ob eine Wertkopie von Sperren auftritt
directive    Prüft Go-Toolchain-Direktiven
errorsas     Prüft, ob Nicht-Zeiger- oder Nicht-Error-Typen an errors.As übergeben werden
framepointer Prüft, ob optimierter Assembler-Code den Frame-Pointer löscht, bevor er gespeichert wird
httpresponse Prüft auf falsche Verwendung von httpresponse
ifaceassert  Prüft Interface-zu-Interface-Typbehauptungen
loopclosure  Probleme mit Referenzen auf Schleifenvariablen
lostcancel   context.WithCancel ohne Verwendung der Cancel-Funktion
nilfunc      Prüft auf nutzlose Vergleiche zwischen Funktionen und nil
printf       Prüft, ob printf-Formatierungsparameter korrekt sind
shift        Prüft auf Schiebeoperationen, die der Integer-Breite entsprechen oder diese überschreiten
sigchanyzer  Prüft auf ungepufferte chan os.Signal
slog         Prüft auf ungültige strukturierte Protokollaufrufe
stdmethods   Prüft, ob Signaturen bekannter Schnittstellenmethoden korrekt sind
stringintconv Prüft String-zu-Integer-Konvertierung
structtag    Prüft, ob Struct-Tags korrekt sind
testinggoroutine Prüft, ob testing.Fatal in einer Goroutine im Test aufgerufen wird
tests        Prüft auf häufige Fehler bei Tests und Beispielen
timeformat   Prüft, ob das Zeitformat bei (time.Time).Format oder time.Parse korrekt ist
unmarshal    Übergibt Nicht-Zeiger- oder Nicht-Schnittstellentypen an unmarshal
unreachable  Prüft auf unerreichbaren Code
unsafeptr    Prüft auf falsche Konvertierung von uintptr zu unsafe.Pointer
unusedresult Prüft auf nicht verwendete Funktionsrückgabewerte

Es handelt sich um Analysegeräte, die auf einen bestimmten Punkt analysieren. Zum Beispiel analysiert das timeformat-Analysegerät, ob der Aufrufformat von time.Format der korrekten Syntax entspricht. Standardmäßig sind alle oben genannten Analysegeräte aktiviert. Zum separaten Aktivieren verwenden Sie folgendes Format:

sh
$ go vet -timeformat main.go

Separat deaktivieren:

sh
$ go vet -timeformat=false main.go

Der Quellcode dieser Analysegeräte befindet sich in cmd/vendor/golang.org/x/tools/go/analysis/passes. Jedes Analysegerät ist eine häufige Fehlerquelle in Go, daher wird dringend empfohlen, den vet-Befehl zur Code-Überprüfung zu verwenden. Darüber hinaus unterstützt es einige andere Flag-Parameter:

  • -V: Nur Version ausgeben und beenden
  • -json: Im JSON-Format ausgeben
  • -c=n: Zeigt die Anzahl der Konfliktzeilen im Kontext an (scheint keine Wirkung zu haben)

Es gibt auch externe Analysegeräte, z. B. shadows, das für die Erkennung von Variablen-Shadowing-Problemen bei Kurzvariablennamen verantwortlich ist. Da es extern ist, muss es mit go install heruntergeladen werden:

sh
$ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latest

Verwendungsformat:

sh
$ go vet -vettool=$(which shadow)

test

sh
$ 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.

Der test-Befehl ist der Befehl in der Go-Toolchain, der Testfunktionen bereitstellt. Diese Funktion ist sehr wichtig. Für eine Software sind umfassende Tests unverzichtbar. Hier wird nur kurz vorgestellt, wie der test-Befehl verwendet wird. Für weitere Informationen zu Tests besuchen Sie: 测试

Neben den Kompilierungsparametern des build-Befehls unterstützt test auch folgende Parameter:

  • -args: Programm-Eingabeparameter
  • -c: Kompiliert die Test-Binärdatei des aktuellen Pakets in das aktuelle Verzeichnis, führt sie aber nicht aus. Benennung im Format pkg.test
  • -exec: Führt vor Testbeginn einige andere Befehle aus
  • -json: Test-Ausgabestil wird JSON
  • -o: Gibt den Pfadnamen der Test-Binärdatei an

Es unterstützt auch viele testflag. Mit dem help-Befehl alle testflag anzeigen:

sh
$ go help testflag
`go test` 命令既接受作用于 `go test` 本身的标志,
也接受作用于生成的测试二进制文件的标志。

`go test` 命令识别以下标志,并用于控制任何测试的执行:
        -bench regexp
        -benchtime t
        -count n
    ......

Einführung einiger häufig verwendeter:

  • -v: Gibt Testergebnisse jedes Use-Cases aus.
  • -timeout duration: Test-Ausführungs-Timeout
  • -skip regexp: Überspringt指定 Test-Use-Cases
  • -short: Lässt lang laufende Test-Use-Cases kürzer laufen
  • -shuffle: Mischt die Ausführungsreihenfolge aller Test-Use-Cases
  • -run regexp: Führt指定 Test-Use-Cases aus
  • -list regexp: Listet jeden Test-Use-Case auf
  • -cpu 1,2,4: Gibt CPU-Anzahl an
  • -count n: Gibt an, wie oft jeder Test-Use-Case ausgeführt werden soll

Die einfachste Verwendung ist ohne Parameter. Es führt alle Test-Use-Cases im aktuellen Paket aus und gibt Ergebnisse aus:

sh
$ ls *_test.go
hello_test.go

$ go test
PASS
ok      golearn 0.522s

Eine bestimmte Testdatei angeben:

sh
$ go test hello_test.go
ok      command-line-arguments  0.041s

Mit dem -v-Parameter können detailliertere Ausgaben angezeigt werden. Es ist sehr häufig verwendet:

sh
$ go test -v hello_test.go
=== RUN   TestHello
    hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok      command-line-arguments  0.041s

Einen bestimmten Test-Use-Case angeben:

sh
$ go test -v -run TestHello
=== RUN   TestHello
    hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok      golearn 0.028s

Während des Tests gibt es zwei Modi für den test-Befehl. Zuerst der Ordner-Modus: Wenn der test-Befehl ohne package-Parameter ausgeführt wird, wird er im Ordner-Modus ausgeführt. Zum Beispiel folgende Befehle:

sh
$ go test
$ go test -v

In diesem Modus ist der Test-Cache deaktiviert. Der andere Modus ist der Listen-Modus: Wenn der package-Parameter nicht leer ist, wird im Listen-Modus getestet. Der Unterschied zum ersteren besteht darin, ob der Test-Cache aktiviert ist. Zum Beispiel folgende:

sh
$ go test -v .
$ go test -v ./...
$ go test .
$ go test -v net/http

Im Listen-Modus kompiliert Go die Testdateien jedes Pakets指定 Pakets zu Binärdateien und führt sie aus. Um wiederholte Tests zu vermeiden, cached Go standardmäßig die Ergebnisse. Bei der zweiten Ausführung wird nicht neu kompiliert. Bei Verwendung folgender Parameter wird der Cache standardmäßig aktiviert:

  • -benchtime
  • -cpu
  • -list
  • -parallel
  • -run
  • short
  • -timeout
  • -failfast
  • -v

Bei Verwendung anderer Parameter als dieser kann der Cache deaktiviert werden. Die offiziell empfohlene Methode ist die Verwendung von -count=1, um den Cache zu deaktivieren. Zum Beispiel:

sh
$ go test -v -count=1 ./...

Anweisungen

Im Gegensatz zu Befehlen sind Go-Anweisungen hartkodiert in Quelldateien vorhanden. Sie haben einen anderen, eher technischen Namen: Compiler-Direktiven (Pragma-Direktiven).

Compiler und Linker ändern ihr Verhalten aufgrund dieser Direktiven, um die Kompilierung zu steuern, ähnlich wie Makros in C. Allerdings sind nicht alle Anweisungen zur Beeinflussung der Kompilierung gedacht. Einige dienen anderen funktionalen Verhaltensweisen. Zum Beispiel wird die generate-Anweisung normalerweise für Code-Generierungsfunktionen verwendet. Diese Anweisungen existieren normalerweise in Form von Kommentaren und haben das Präfix //go:, ohne Leerzeichen dazwischen, z. B. die //go:generate-Anweisung. Alle Anweisungstypen sind insgesamt in zwei Kategorien unterteilt:

  • Funktionale Anweisungen: Dies sind von Go bereitgestellte funktionale Anweisungen, die frei verwendet werden können, z. B. generate, embed, build.
  • Compiler-Anweisungen: Diese Anweisungen müssen mit Vorsicht verwendet werden. Unsachgemäße Verwendung kann zu unvorhersehbaren Ergebnissen führen.

Mit Ausnahme funktionaler Anweisungen können die meisten Anweisungen nur auf Funktionssignaturen wirken. Für Compiler-Anweisungen können Sie den Befehl go doc compile ausführen, um ihre Anweisungen anzuzeigen. Für alle Anweisungen finden Sie Informationen in cmd/compile/internal/ir/node.go: 440.

generate

sh
$ go help generate
usage: go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]

Die generate-Anweisung ist, wie der Name schon sagt, mit Generierung verbunden. Normalerweise dient sie zur Ausführung von Befehlen, die Code generieren und Quellcode aktualisieren. Tatsächlich kann sie jedoch beliebige Befehle ausführen. Im Gegensatz zu anderen Anweisungen gibt es einen speziellen Befehl, der alle in Quelldateien befindlichen generate-Anweisungen ausführen kann. Sie kann Dateinamen oder Paketnamen als Eingabeparameter verwenden, um anzugeben, welche Dateien generate-Anweisungen ausgeführt werden sollen. Hier sind ihre anderen Parameter:

  • -run=regex: Führt指定 generate-Anweisungen aus
  • -skip=regex: Überspringt指定 generate-Anweisungen
  • -n: Gibt die auszuführenden Befehle aus
  • -x: Gibt die während des Prozesses ausgeführten Befehle aus
  • -v: Gibt die verarbeiteten Dateien aus

Darüber hinaus unterstützt die in generate-Anweisungen ausgeführte Befehle folgende eingebaute Parameter:

  • $GOARCH: CPU-Architektur
  • $GOOS: Betriebssystem
  • $GOFILE: Dateiname
  • $GOLINE: Zeilennummer
  • $GOPACKAGE: Paketname
  • $GOROOT: Go Root
  • $DOLLAR: Dollar-Zeichen
  • $PATH: PATH-Umgebungsvariable

Ein Beispiel, nur ein Kommentar ohne Code:

go
package main

//go:generate echo "hello world!"

Befehl ausführen:

$ go generate .
hello world!

Dieses Beispiel führt einen Go-Befehl aus:

go
package main

//go:generate go version

Befehl ausführen:

sh
$ go generate .
go version go1.21.3 windows/amd64

Die generate-Anweisung kann zur Ausführung beliebiger Befehle verwendet werden, z. B. Swagger zur Generierung von API-Dokumenten oder Wire zur Generierung von IOC-Code. Allerdings ist diese Anweisung nicht für besonders komplexe Befehle geeignet. Sie eignet sich für kurze Befehle. Bei komplexen Anforderungen können Skripte oder Makefile als Ersatz verwendet werden.

embed

Die embed-Anweisung wurde in Version 1.16 hinzugefügt. Ihre Funktion besteht darin, statische Dateien zusammen in die Binärdatei zu packen, z. B. HTML-Vorlagen. Das Format lautet wie folgt:

go
//go:embed pattern

pattern kann ein Glob-Ausdruck, ein Ordner oder eine bestimmte Datei sein. Ein Beispiel:

go
package main

import "embed"

//go:embed *
var static embed.FS

Die embed-Anweisung erfordert, dass sie sich über einer globalen Variable vom Typ embed.FS befindet. Beachten Sie, dass es eine globale Variable sein muss. Die Verwendung erfordert den Import des embed-Pakets. In diesem Beispiel repräsentiert *, dass alle Dateien im aktuellen Ordner in die Binärdatei gepackt werden. Allerdings werden Ordner, die mit . beginnen, nicht允许.

Das folgende Beispiel zeigt das Lesen von Inhalten aus eingebetteten Dateien:

go
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))
}

Es hat nur drei Methoden. Die Verwendung unterscheidet sich nicht von einem normalen Dateisystem. Da es das io/Fs-Interface implementiert, kann es auch als Fs-Objekt übergeben werden:

go
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)

Das folgende Beispiel zeigt das Einbetten von HTML-Dateien über die embed-Anweisung und den Zugriff über einen HTTP-Dienst:

go
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)
}

Ergebnis nach访问:

sh
$ 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>

Die embed-Anweisung unterstützt auch, dass der Typ der globalen Variable []byte sein kann. Zum Beispiel:

go
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)
}

Der erzielte Effekt ist ähnlich wie im vorherigen Beispiel:

sh
$ 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

Im Abschnitt build-编译控制 wurde die Verwendung der // +build-Anweisung zur Steuerung des Kompilierungsverhaltens erläutert. Die //go:build-Anweisung ist neu in Version 1.17 und soll die vorherige Anweisung ersetzen. Allerdings sind wir jetzt bei Version 1.21, und sie wurde noch nicht ersetzt. Schätzungsweise werden sie in Zukunft koexistieren. Zur neuen Anweisung gibt es auch eine offizielle Dokumentation: build constraints. Ihre Funktion unterscheidet sich nicht von der vorherigen, aber die Syntax ist strenger und unterstützt boolesche Ausdrücke. Ein Beispiel:

go
//go:build (linux && 386) || (darwin && !cgo)

package pkg_name

Diese Methode ist viel lesbarer als die ursprüngliche.

line

Die line-Anweisung beeinflusst die Zeilennummer, Spaltennummer und den Dateinamen der nächsten Zeile. Ihre Wirkung beschränkt sich darauf und wird meist zur Debugging von Fehlern verwendet. Zum Beispiel ändert sie bei einem Fehler die vom Compiler ausgegebenen Informationen:

go
package main

var a undefinedType

func main() {

}

Normalerweise gibt der Compiler aus:

.\main.go:3:7: undefined: undefinedType

Aber mit der line-Anweisung sieht es anders aus:

go
package main

//line abc.go:10:100
var a undefinedType

func main() {

}

Dann lautet die Ausgabe:

abc.go:10:106: undefined: undefinedType

Aufgrund historischer Gründe ist die line-Anweisung auch die einzige Anweisung, deren Verwendung sich von anderen Anweisungen unterscheidet. Das Format lautet:

go
//line filename:line:column

Wie Sie sehen können, benötigt sie kein go: als Präfix.

linkname

Diese Anweisung kann verwendet werden, um Funktionen oder globale Variablen anderer Pakete zu verknüpfen, selbst wenn sie private Typen sind. Diese Operation tritt häufig in der Standardbibliothek, insbesondere in runtime, auf. Einige Funktionen haben keinen Funktionskörper und werden auf diese Weise implementiert. Ein anderer Teil der Funktionen mit leerem Funktionskörper wird durch Assembly implementiert. Hier ist die Verwendung. Das Format lautet:

go
//go:linkname 链接类型名称 被链接的类型

Und vor der Verwendung muss beispielsweise das unsafe-Paket importiert werden. Ein einfaches Beispiel für die Verknüpfung privater Typen in der Standardbibliothek:

go
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")))
}

Ausgabe:

15395306441938000233

Es verknüpft die private Funktion runtime.memhash mit unserer selbst deklarierten Funktion. Diese Funktion hat keinen Funktionskörper, nur eine Signatur, und dient nur als Träger. memhash berechnet den Hash-Wert basierend auf dem Speicher, gegeben einem Zeiger, Hash-Seed und Speicher-Offset. Dieser Verknüpfungsprozess wird zur Kompilierzeit abgeschlossen.

Wenn es nicht die Standardbibliothek ist, ist die Situation etwas anders. Zum Beispiel gibt es eine test-Funktion im example-Paket. Vor der Verknüpfung muss dieses Paket anonym importiert werden:

go
package example

// 一个私有类型,外界无法访问。
func test() string {
  return "a"
}
go
package main

import (
  "fmt"
  _ "golearn/example"
  _ "unsafe"
)

//go:linkname test golearn/example.test
func test() string

func main() {
  fmt.Println(test())
}

Ausgabe:

a

Wie Sie sehen können, war die Verknüpfung erfolgreich. Diese Methode kann das Go-Modulsystem umgehen und beliebig agieren. Es wird jedoch nicht empfohlen, sie großflächig zu verwenden, es sei denn, Sie wissen, was Sie tun.

noinline

Die noinline-Anweisung bedeutet, dass eine Funktion keine Inline-Optimierung erlaubt, selbst wenn sie sehr einfach ist. Ein einfaches Beispiel:

go
package main

func val() string {
  return "val"
}

func main() {
  var c = val()
  _ = c
}

val ist eine sehr einfache Funktion, die einen String-Literal zurückgibt. Da sie zu einfach ist und das Ergebnis immer vorhersehbar ist, wird sie beim Kompilieren vom Compiler wie folgt optimiert:

go
package main

func main() {
  var c = "val"
  _ = c
}

Schauen wir uns die Assembly-Form an. Wie Sie sehen können, wurde kein Aufruf der val-Funktion gefunden:

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)
RET

Als Nächstes fügen wir die noinline-Anweisung hinzu:

go
package main

//go:noinline
func val() string {
  return "val"
}

func main() {
  var c = val()
  _ = c
}

Schauen wir uns erneut die Assembly-Form an:

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
RET

Dieses Mal können Sie deutlich den main.val-Aufruf sehen, was genau die Funktion der noinline-Anweisung ist: Verhindern von Funktions-Inlining während der Compiler-Optimierung.

nosplit

Die nosplit-Anweisung überspringt die Stack-Overflow-Erkennung. Da das Go-Nebenläufigkeits-Scheduler-Modell ein präemptives Scheduler-Modell ist, kann diese Anweisung verwendet werden, wenn eine Funktion sehr low-level-Code ausführt und andere Goroutinen beim Aufruf dieser Funktion nicht geeignet sind, präemptiert zu werden:

go
//go:nosplit
func nospilitFn()

Nach Verwendung dieser Anweisung findet kein Stack-Wachstum mehr statt.

noescape

noescape, wie der Name schon sagt, hat mit Escape zu tun. Es bedeutet, dass die aktuelle Funktion kein Memory-Escape-Verhalten auftritt. Nach der Ausführung werden alle Ressourcen回收, und diese Funktion muss nur eine Signatur ohne Funktionskörper haben. In diesem Fall wird die Implementierung der Funktion normalerweise durch Assembly realisiert.

Zum Beispiel verwendet das zuvor verwendete memhash diese Anweisung:

go
//go:noescape
//go:linkname memhash runtime.memhash
func memhash(p unsafe.Pointer, h, s uintptr) uintptr

Auf diese Weise führt der Compiler keine Escape-Analyse durch. Voraussetzung ist, dass Sie sicherstellen müssen, dass kein Escape auftritt. Wenn es doch auftritt, sind die Folgen unbekannt.

uintptrescapes

Die uintptrescapes-Anweisung bedeutet, dass uintptr-Typ-Parameter in dieser Funktion in Zeigerwerte konvertiert wurden und auf den Heap escaped sind und am Leben gehalten werden müssen. Diese Anweisung wird im Allgemeinen für einige low-level-Systemaufrufe verwendet. In den meisten Fällen muss sie nicht verstanden werden:

go
//go:uintptrescapes
func nospilit(ptr uintptr) uintptr

Früher gab es eine notinheaps-Anweisung, die angab, dass ein Typ keinen Speicher auf dem Heap allozieren darf. Sie wurde in einer unbekannten Version entfernt.

norace

Die norace-Anweisung bedeutet, dass der Speicherzugriff einer Funktion keine Race-Analyse erfordert. Wird normalerweise verwendet, wenn low-level-Code ausgeführt wird und keine Race-Analyse geeignet ist:

go
//go:norace
func low_level_code(ptr uintptr) uintptr

TIP

Einige Anweisungen sind auf die Verwendung durch das runtime-Paket beschränkt und können extern nicht verwendet werden. Sie betreffen tiefere Dinge. Weitere Informationen finden Sie unter Runtime-only compiler directives.

Golang by www.golangdev.cn edit