Skip to content

Ligne de commande

Les commandes dans Go comprennent toute une chaîne d'outils, ces commandes couvrent la documentation, le formatage, l'inspection du code, la compilation, les tests, la gestion des dépendances et bien d'autres aspects, on peut dire qu'elles couvrent tous les aspects du développement Go.

text
bug         Signaler un bug
build       Compiler les packages et les dépendances
clean       Nettoyer les fichiers objets
doc         Afficher la documentation dans le code source
env         Afficher les informations sur les variables d'environnement Go
fix         Résoudre les problèmes de compatibilité API dus aux changements de version de go
fmt         Formater le code source
generate    Génération de code
get         Ajouter des dépendances
install     Installer et compiler les packages
list        Commande de liste de packages/modules
mod         Commande de maintenance des modules
work        Commande de maintenance des espaces de travail
run         Compiler et exécuter
test        Tester
tool        Exécuter l'outil go spécifié
version     Afficher les informations de version de go
vet         Analyser et signaler les problèmes potentiels dans le code source

Cet article décrit et présente simplement leur utilisation, tout le contenu est référencé depuis la documentation officielle, pour en savoir plus sur les détails, rendez-vous sur cmd/go.

help

La première commande à connaître est la commande help, qui permet de lire l'utilisation des commandes. Il y a deux façons de l'utiliser, si vous souhaitez obtenir des informations d'utilisation brèves, vous pouvez ajouter le drapeau -h après la commande spécifiée, par exemple

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

Go affichera brièvement l'utilisation de la commande, et il indique également que pour obtenir des informations plus détaillées, vous devez utiliser la commande help

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

Utilisez habilement la commande help, grâce à elle vous pouvez obtenir beaucoup d'informations sur les commandes.

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

La commande doc affiche les commentaires de documentation pour les packages, constantes, fonctions, types, variables, méthodes et même les champs de structure spécifiés. Sans aucun paramètre, elle affiche les commentaires du package actuel

sh
$ go doc

Vous pouvez également spécifier un package à consulter, par exemple pour afficher la documentation du package runtime

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

Ou un certain type

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

Ou une certaine fonction

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.

Elle dispose des drapeaux courants suivants

  • -u : Afficher les types privés
  • -all : Afficher toute la documentation d'un package spécifié
  • -short : Affiche uniquement une brève description en une ligne
  • -src : Affiche le code source
  • -cmd : Affiche également la documentation du code pour les packages qui appartiennent aux commandes go.

Par exemple, pour afficher la variable runtime.inf, qui est une variable non exposée

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

var inf = float64frombits(0x7FF0000000000000)

Bien utiliser la commande doc peut vous aider à lire la documentation plus facilement.

Une autre façon de lire la documentation des commandes est de lire le code source, car la documentation de certaines commandes n'est pas écrite de manière très détaillée, alors que le code source contient des explications plus détaillées. Comme ces commandes sont toutes écrites en go, la lecture est très pratique. Ces commandes sont situées dans le package src/cmd, chaque sous-package est une commande séparée, le point d'entrée se trouve dans le fichier 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,
    }
}

Ici, vous trouverez toutes les sous-commandes de go, ainsi que leurs informations de documentation d'aide.

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.

Cette commande n'a aucun paramètre ni drapeau, elle utilise votre navigateur par défaut pour accéder à la page des issues du dépôt github.com/golang/go, ce qui vous permet de signaler des bugs, et n'a aucune autre fonction.

version

La commande version permet d'afficher les informations de version de go.

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

Sans aucun paramètre, elle affiche la version actuelle du langage go

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

Elle accepte également les chemins de fichiers comme paramètres, et affiche la version de go utilisée pour compiler tous les fichiers binaires identifiables dans ce chemin.

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

Le paramètre -v indique à la commande version d'essayer d'afficher la version go des fichiers non identifiables, le paramètre -m affiche les informations de module des fichiers binaires, ainsi que certains paramètres de compilation, voici un exemple simple.

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 est lui-même un fichier binaire, en fait, sans aucun paramètre, go version affiche la version du langage go de son propre fichier binaire, car toute la chaîne d'outils de cmd/go est implémentée par le langage go lui-même.

env

La commande env permet d'afficher toutes les variables d'environnement go, la modification de ces variables d'environnement affectera le comportement de la chaîne d'outils go.

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

Exécuter cette commande sans aucun paramètre affiche les valeurs de toutes les variables d'environnement go

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

Utiliser le nom d'une variable d'environnement comme paramètre permet d'afficher uniquement la valeur de cette variable

sh
$ go env GO111MODULE
on

Ajouter -json permet d'afficher sa forme json

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

Utiliser le drapeau -w, et avec un paramètre sous la forme var=value, modifie définitivement la valeur d'une variable

sh
$ go env -w GO111MODULE=on

Utiliser le drapeau -u permet de rétablir une variable à sa valeur par défaut

sh
$ go env -u GO111MODULE

Exécuter go help environment permet d'afficher la description de chaque variable d'environnement

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

Voici quelques variables d'environnement couramment utilisées

GOVERSION

La valeur de cette variable d'environnement dépend de la version du langage go, et le numéro de version provient du fichier $GOROOT/VERSION, qui enregistre la version actuelle de go et l'heure de construction.

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

La valeur de la variable runtime.Version est la même que celle de GOVERSION, et cette variable d'environnement ne peut pas être modifiée.

GOENV

Il y a un fichier de configuration par défaut nommé go.env dans le répertoire $GOROOT

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

Son format est simplement key=value, les valeurs des variables d'environnement modifiées via la commande go env -w key=value seront écrites dans le fichier de configuration. Cependant, il est également possible de ne pas utiliser le fichier de configuration par défaut, la variable d'environnement GOENV peut spécifier manuellement l'adresse du fichier de configuration env, et la valeur de la variable d'environnement GOENV ne peut être remplacée que par les variables d'environnement du système d'exploitation, et ne peut pas être modifiée par la commande go env -w.

GOHOSTARCH

Représente l'architecture CPU de la machine locale, utilisée uniquement pour l'affichage, la valeur de cette variable d'environnement n'est pas lue depuis le fichier de configuration et ne peut pas être modifiée.

GOHOSTOS

Représente le système d'exploitation de la machine locale, utilisée uniquement pour l'affichage, la valeur de cette variable d'environnement n'est pas lue depuis le fichier de configuration et ne peut pas être modifiée.

GOOS

Lors de la compilation, la valeur de GOOS détermine le système cible pour lequel le code source sera compilé en fichier binaire, la valeur par défaut est GOHOSTOS, c'est-à-dire le système d'exploitation de la machine locale, il y a les options suivantes

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

Les systèmes d'exploitation réellement pris en charge ne se limitent pas à ceux-ci, utilisez la commande go tool dist list pour afficher toutes les valeurs prises en charge

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

Lors de la compilation, la valeur de GOARCH détermine l'architecture CPU utilisée lors de la compilation, la valeur par défaut est GOHOSTARCH, c'est-à-dire l'architecture CPU de la machine locale, il y a les options suivantes

  • amd64
  • 386
  • arm
  • ppc64

Les architectures réellement prises en charge ne se limitent pas à celles-ci, utilisez la commande go tool dist list pour afficher toutes les valeurs prises en charge

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

Il est à noter que GOOS et GOARCH ne peuvent pas être combinés arbitrairement, certains systèmes d'exploitation ne prennent en charge que des architectures CPU spécifiques.

GOROOT

GOROOT représente le répertoire racine de l'installation du langage go, la valeur de GOROOT ne peut pas être modifiée directement, et ne peut être remplacée que par les variables d'environnement du système d'exploitation.

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

Il y a plusieurs répertoires ou fichiers importants dans le répertoire racine

  • lib, stocke certaines dépendances, pour l'instant il n'y a qu'une bibliothèque contenant des informations de fuseau horaire de divers pays du monde, située dans $GOROOT/lib/time, les fichiers binaires compilés ne contiendront pas ces informations de fuseau horaire.

  • pkg, stocke certaines bibliothèques d'outils et fichiers d'en-tête, par exemple la commande go tool recherchera les fichiers binaires de la chaîne d'outils go dans le répertoire $GOROOT/pkg/tool

  • bin, stocke les fichiers binaires, par défaut il n'y a que les fichiers exécutables go et gofmt, $GOROOT/bin doit être ajouté aux variables système, sinon les commandes go ne peuvent pas être utilisées.

  • src, stocke le code source go

  • VERSION, ce fichier stocke les informations de version du langage go

  • go.env, ce fichier est le fichier de configuration env par défaut

GOPATH

La valeur par défaut de GOPATH est $HOME/go, la valeur de cette variable d'environnement spécifie où rechercher les fichiers importés lors de l'analyse des instructions import. Au début, avant gomod, GOPATH était spécialement utilisé pour stocker diverses bibliothèques tierces, sa structure est la suivante

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)

Après la naissance de gomod, GOPATH est simplement devenu un endroit pour stocker les dépendances téléchargées avec go get, ainsi que pour stocker les fichiers binaires téléchargés et compilés avec go install. Il est à noter que l'emplacement de GOPATH ne peut pas être le même que GOROOT, sinon cela n'aura aucun effet.

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

Jusqu'à présent, au moment où j'écris cet article, la version du langage go est déjà arrivée à go1.21.3, à l'exception des projets très anciens, presque personne n'utilise plus gopath pour gérer les dépendances.

GOBIN

GOBIN est utilisé pour stocker les fichiers binaires exécutables tiers téléchargés et compilés avec go install, sa valeur par défaut est $GOPATH/bin. Comme $GOROOT/bin, ce répertoire doit être ajouté aux variables d'environnement du système d'exploitation, sinon les fichiers binaires du répertoire GOBIN ne peuvent pas être utilisés.

GOMODCACHE

GOMODCACHE représente l'emplacement de stockage des dépendances téléchargées avec go get, la valeur par défaut est $GOPATH/pkg/mod. Son format de stockage est le suivant

$GOMODCACHE/domain/username/project@version

Il y aura également un répertoire nommé sumdb au même niveau, utilisé pour stocker les informations relatives à la base de données de somme de contrôle des dépendances.

GOCACHE

Stocke les informations de cache utilisées pour la compilation, sa valeur par défaut est $HOME/.cache/go-build, un fichier README sera généré dans ce répertoire.

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.

Chaque build génère de nombreux fichiers, go met en cache ces fichiers pour les réutiliser lors de la prochaine compilation.

GOTEMPDIR

Utilisé pour les fichiers temporaires générés lors de la compilation, tels que les fichiers binaires temporaires à exécuter avec go run. Sa valeur par défaut est le répertoire temporaire spécifié par le système d'exploitation, /tmp sur mac ou linux, %TEMP% sur windows, et peut également être modifié pour un emplacement spécifié par l'utilisateur.

GO111MODULE

Cette variable d'environnement indique quelle méthode utiliser pour gérer les dépendances des projets go, il y a trois valeurs disponibles

  • off, désactive gomod, utilise gopath, et ignore tous les fichiers go.mod
  • on, utilise gomod, n'utilise pas gopath (par défaut).
  • auto, détection automatique, si le fichier du projet contient go.mod, utilise gomod pour la gestion

TIP

Pourquoi s'appelle-t-il GO111MODULE, et pas simplement GOMODULE, parce que gomod a été introduit pour la première fois dans la version go1.11.

GOPROXY

Le proxy de module go, la valeur par défaut est https://proxy.golang.org,direct, les url sont séparées par des virgules, direct signifie utiliser directement VCS pour sauter le proxy de module, ce dernier n'est exécuté que si le premier n'est pas accessible, il y a aussi une option disponible off, qui signifie interdire le téléchargement de tout module. En outre, GOPROXY peut également être une adresse de fichier, par exemple

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

Utiliser go get -x permet de voir les commandes exécutées lors du processus de téléchargement des dépendances, et donc de savoir si le proxy est utilisé.

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

L'utilisation d'un proxy de module peut efficacement améliorer la vitesse de téléchargement des modules, pour les utilisateurs en Chine, sans proxy, ils ne peuvent généralement pas accéder au proxy officiel par défaut, voici les proxies de modules tiers publics et fiables actuellement disponibles

  • https://proxy.golang.com.cn, open-source et fournit également des services d'entreprise
  • https://goproxy.cn, fourni et open-source par Qiniu Cloud

Il existe également des solutions de proxy de module auto-hébergées open-source : goproxy

GOSUMDB

GOSUMDB est utilisé pour définir l'adresse de la base de données de détection de somme de contrôle des bibliothèques de dépendances, par défaut sum.golang.org, lorsque vous définissez un proxy, go accédera à la base de données de somme de contrôle via le proxy.

GOPRIVATE

La variable d'environnement GOPRIVATE est utilisée pour définir les bibliothèques privées, les bibliothèques correspondantes ne seront pas vérifiées via sumdb, et n'utiliseront pas de proxy, les dépendances seront téléchargées directement via VCS. Elle prend en charge les paramètres de caractères génériques, séparés par des virgules, comme illustré ci-dessous, toutes les dépendances avec le suffixe corp.example.com et nommées github.com/gohper/myproject n'utiliseront pas de proxy ni sumdb.

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

Vous pouvez également définir directement un utilisateur ou une organisation

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

GONOPROXY

Indique quelles dépendances n'ont pas besoin d'utiliser de proxy, les règles sont les mêmes que GOPRIVATE, et remplacent GOPRIVATE.

GONOSUMDB

Indique quelles dépendances n'ont pas besoin d'utiliser la base de données de somme de contrôle, les règles sont les mêmes que GOPRIVATE, et remplacent GOPRIVATE.

GOINSECURE

Indique quelles dépendances doivent être téléchargées directement via VCS, les règles sont les mêmes que GOPRIVATE, et sont remplacées par GONOPROXY et GONOSUMDB.

GOVCS

Définit le système de contrôle de version pour la gestion des modules, par défaut public:git|hg,private:all. Peut également limiter les VCS pour des noms de domaine spécifiés, par exemple

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

Dans les restrictions ci-dessus, github ne peut utiliser que git, evil.com n'est pas autorisé, utilisez | pour représenter plusieurs VCS. Si vous ne faites aucune restriction, vous pouvez définir comme suit

GOVCS=*:all

Si vous ne permettez l'utilisation d'aucun VCS, vous pouvez définir comme suit

GOVCS=*:off

GOWORK

Définit si l'espace de travail est activé, par défaut vide c'est-à-dire activé, si défini sur off, il n'est pas activé, et ignorera tous les fichiers go.work.

GOTOOLDIR

Définit l'emplacement de la chaîne d'outils go à utiliser, par défaut $GOROOT/pkg/tool, la chaîne d'outils par défaut est également stockée à cet emplacement.

GODEBUG

Définit les options de débogage, contrôle certains comportements d'exécution des programmes go sous forme de paires clé-valeur, par exemple

GODEBUG=http2client=0,http2server=0

Ces paramètres sont destinés à faciliter le retour aux anciens comportements de go en cas de changements incompatibles lors des mises à jour de version, par exemple dans 1.21, panic(nil) n'est plus autorisé, pour cette raison, go officiel a spécialement enregistré GODEBUG History, consultez GODEBUG pour plus de détails.

CGO_ENABLED

Indique si cgo est activé, par défaut 1, c'est-à-dire activé, défini sur 0 pour désactiver.

Les variables d'environnement ci-dessus sont les plus couramment utilisées, pour certaines moins couramment utilisées comme CGO, WASM, etc., si vous êtes intéressé, vous pouvez les explorer vous-même.

build

Go prend en charge deux types de compilateurs, gccgo et gc. gcc est un ancien compilateur c/c++, prend en charge plusieurs langages dont go, ce dernier gc ne signifie pas garbage collection, il signifie go compiler, le langage go a terminé son auto-hébergement en go1.5, gc est un compilateur entièrement écrit en langage go, son code source est situé dans le package cmd/compile, comme il est entièrement implémenté en langage go, il est donc très pratique pour comprendre et apprendre son mécanisme interne. Par défaut, le compilateur utilise gc pour compiler. Soit dit en passant, le débogueur go existe également en deux versions, gdb et dlv, le premier est un ancien débogueur c/c++, prend en charge plusieurs langages dont go, le second est un débogueur écrit en langage go, plus convivial pour le langage go, il est également open-source, il est recommandé d'utiliser ce dernier. La commande build sert à compiler les fichiers source go en fichiers binaires exécutables, vous ferez l'expérience d'une compilation très rapide, ce qui est l'une des caractéristiques du langage go.

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

Elle accepte trois paramètres, l'un est le chemin de sortie du fichier indiqué par le drapeau -o, l'autre est les drapeaux de construction build flags utilisés pour définir le comportement de compilation, et le dernier est le package à compiler, ce paramètre doit être placé en dernier. Voici un exemple simple, sans utiliser de drapeaux de construction.

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

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

./bin/golearn.exe représente le chemin de sortie, golearn représente le module à compiler, cela peut également être un fichier d'entrée ou un répertoire. Voici un exemple simple avec le fichier d'entrée main.go comme cible de compilation.

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

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

Lors de la compilation, il ignore tous les fichiers se terminant par _test.go, car ces fichiers sont par convention des fichiers de test.

En outre, la commande build prend également en charge un nombre considérable de drapeaux de construction pour contrôler certains comportements lors de la compilation.

  • -x : Affiche les instructions détaillées du processus de compilation
  • -n : Similaire à -x, mais la différence est qu'elle affiche uniquement ces instructions, mais ne les exécute pas réellement.
  • -v : Affiche les packages compilés
  • -p : Le nombre de processus simultanés pendant la compilation
  • -a : Force la reconstruction, même si elle est déjà à jour.
  • -compiler : Spécifie quel compilateur utiliser, gccgo ou gc, ce dernier est un compilateur écrit en go.
  • -race : Active la détection de course
  • -msan : Active l'analyse de mémoire
  • -asan : Active l'analyse d'adresse
  • -cover : Active la détection de couverture de code
  • -buildmode : Spécifie le mode de compilation, avec les options archive, c-archive, c-shared, default, shared, exe, pie, plugin.
  • -pgo, spécifie le fichier pgo
  • -trimpath : Élimine le préfixe de chemin des fichiers source, par exemple le chemin relatif /var/lib/go/src/main.go, après élimination, le nom de fichier obtenu via runtime lors de l'exécution n'est que le chemin relatif par rapport au chemin du module /main.go, après avoir activé cette option, le temps de compilation augmentera considérablement, d'environ 20-40%, selon le nombre de fichiers.
  • -toolexec, certaines commandes go exécutées avant la compilation, au format -toolexec 'cmd args'.
  • -gcflags : Spécifie certains tags du compilateur gc
  • -gccgoflags : Spécifie certains tags du compilateur gccgo
  • -ldflags : Spécifie certains tags de l'outil link

Pour certains paramètres de transmission comme ldflags, vous pouvez transmettre des paramètres comme "-help" pour obtenir leurs valeurs possibles, par exemple

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

Ce qui précède sont les plus couramment utilisés, pour d'autres moins couramment utilisés, vous pouvez les explorer vous-même.

gcflags

Via gcflags, vous pouvez transmettre certains paramètres au compilateur gc pour contrôler des comportements spécifiques, son format d'utilisation est -gcflags="pattern=args list", args list est la liste des paramètres, pattern est la portée d'application, il y a les valeurs disponibles suivantes

  • main, le chemin du package de premier niveau où se trouve le fichier d'entrée
  • all, le module actuel et toutes les dépendances du mode actuel
  • std, la bibliothèque standard
  • cmd, agit sur tous les fichiers source du package cmd
  • Caractères génériques, comme ., ./..., cmd/....

La règle pattern s'applique à tous les drapeaux qui prennent en charge ce format, comme ldflags. Utilisez la commande suivante pour afficher les valeurs disponibles des paramètres

sh
$ go build -gcflags -help
用法:compile [选项] file.go...
  -%    调试非静态初始化器
  -+    编译运行时
  -B    禁用边界检查
  -C    禁用错误消息中的列号打印
  -D path
        设置本地导入的相对路径
  -E    调试符号导出
  -I directory
        添加目录到导入搜索路径
  -K    调试缺失的行号
  -L    对于受 //line 指令影响的错误位置,同时显示实际源文件名
  -N    禁用优化
  -S    打印汇编列表
  -V    打印版本并退出
  -W    类型检查后调试解析树
  ......

Voici quelques paramètres couramment utilisés

  • -S : Affiche la forme assembleur du code
  • -N : Désactive l'optimisation de compilation
  • -m : Affiche les décisions d'optimisation
  • -l : Désactive l'inlining de fonction
  • -c : Le nombre de processus simultanés de compilation
  • -dwarf : Génère des symboles DWARF

Par exemple, si vous souhaitez afficher la forme assembleur du code, vous pouvez utiliser le paramètre -S, et vous devez également désactiver l'optimisation et l'inlining, afin de restaurer sa forme originale, comme suit

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

Via ldflags, vous pouvez transmettre certains paramètres à l'éditeur de liens pour contrôler des comportements spécifiques, utilisez la commande suivante pour afficher toutes les valeurs disponibles de ldflags, près d'une vingtaine.

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

Le paramètre -X de ldflags est une fonctionnalité très pratique, il permet de définir la valeur des variables de type chaîne d'un package spécifié lors de l'édition de liens. Grâce à cette fonctionnalité, nous pouvons facilement injecter des métadonnées lors de la compilation. Et comme ce n'est qu'une variable, il est également pratique de l'obtenir lors de l'exécution, voici un exemple simple.

go
package main

import "fmt"

var (
  Version string
)

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

Exécutez la commande

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

Après l'exécution, la somme de contrôle sha1 du commit git sera affichée.

5e3fd7a

D'autres paramètres plus pratiques incluent

  • -w : Ne génère pas DWARF, qui est une information pratique pour déboguer le code source.
  • -s : Désactive la table des symboles

Ces deux derniers sont généralement utilisés ensemble, ce qui peut réduire considérablement la taille du fichier binaire compilé, d'environ 40%-50%, l'inconvénient est également évident, impossible de déboguer, voici un exemple.

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

Compilation croisée

La compilation du langage go a deux caractéristiques principales, la première est la rapidité, l'autre grande caractéristique est la compilation croisée, la compilation croisée signifie qu'il est possible de compiler localement en code cible d'autres systèmes, par exemple compiler sur windows en fichier binaire pour linux ou darwin, et vice versa. La compilation croisée prend en charge un très grand nombre de langages, ce n'est pas quelque chose de rare, mais la compilation croisée du langage go est très simple, il suffit des étapes suivantes

  1. Définir la variable d'environnement GOOS, choisir votre système d'exploitation cible
  2. Définir la variable d'environnement GOARCH, choisir votre architecture CPU cible
  3. Utiliser go build comme d'habitude pour compiler

L'ensemble du processus est très court, pas besoin d'utiliser d'outils ou de configurations supplémentaires, et la vitesse est aussi rapide que d'habitude. Comme illustré ci-dessous

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

La première étape SET CGO_ENABLED=0 désactive cgo, une fois que votre code utilise cgo, alors la compilation croisée ne peut pas être utilisée normalement. La deuxième étape SET GOOS définit le système cible, les options disponibles sont linux, darwin, windows, netbsd. La troisième étape définit l'architecture CPU, SET GOARCH, les options disponibles sont amd64, 386, arm, ppc64. La dernière étape consiste à compiler comme d'habitude.

Contrôle de compilation

La commande build peut atteindre le contrôle de compilation via tags, qui existe dans le code source sous forme d'instructions, prenons un exemple, le fichier product.go

go
// +build product

package main

import "fmt"

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

Le fichier debug.go

go
// +build debug

package main

import "fmt"

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

Ils ont tous une instruction // +build, qui indique dans quelles conditions ils seront compilés. Le format de base est

go
// +build tag1 tag2

package pkg_name

Il y a plusieurs règles à respecter

  1. // et +build doivent être séparés par un espace
  2. Il doit être situé au-dessus de la déclaration du package
  3. Doit être séparé de la déclaration du package par une ligne vide

En outre, il peut également atteindre le contrôle logique via de simples espacements, l'espace représente OR, la virgule représente AND, ! représente NOT. Par exemple

go
// +build windows linux

package pkg_name

Signifie que le fichier actuel sera compilé sous les plateformes windows ou linux.

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

package pkg_name

Cet exemple signifie qu'il sera compilé uniquement sous la plateforme windows architecture amd64 et sans cgo activé, ou sous la plateforme linux architecture i386 et avec cgo activé. Si vous ne voulez tout simplement pas qu'un fichier participe à la compilation, vous pouvez utiliser ignore.

go
// +build ignore

package pkg_name

Il peut également y avoir des instructions sur plusieurs lignes

go
// +build windows
// +build amd64

package pkg_name

Les instructions sur plusieurs lignes sont traitées de manière AND. Pour les tags de plateforme et d'architecture, go les transmet automatiquement lors de la compilation, nous pouvons également transmettre des tags personnalisés, prenons les deux fichiers du début comme exemple

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

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

Vous pouvez voir que la sortie est différente lorsque différents tags sont transmis, l'objectif du contrôle de compilation est ainsi atteint.

run

Les commandes run et build compilent toutes deux le code source, la différence est que la commande run s'exécute directement après la compilation. La commande run, afin d'accélérer la vitesse de compilation, ne génère pas d'informations de débogage pendant le processus de compilation, donc ne prend pas en charge le débogage, et génère uniquement un fichier binaire temporaire, généralement stocké dans le répertoire GOTMPDIR, par exemple /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.

Elle prend également en charge les drapeaux de construction de la commande build, et fournit également un paramètre -exec pour indiquer quel programme utiliser pour exécuter le fichier binaire, [arguments...] fait référence aux paramètres d'exécution du programme. Voici un exemple

go
package main

import (
  "fmt"
  "os"
)

var (
  Version string
)

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

Exécuter avec go run

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

Dans l'ensemble, l'utilisation n'est pas très différente de go build, donc je ne vais pas trop m'étendre.

tool

La commande tool n'a aucune fonction en soi, son rôle est d'appeler directement les outils du répertoire cmd/, par exemple cmd/compile est le compilateur intégré. Via go tool, vous pouvez appeler directement ces outils, sans avoir à exécuter manuellement les fichiers binaires de ces outils.

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

Utiliser le paramètre -n pour afficher tous les paramètres de commande pris en charge

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

Ces outils sont stockés dans le répertoire GOROOT/pkg/tool, et sont regroupés en fonction du système d'exploitation et de l'architecture CPU, comme suit.

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*

Utilisez le format go doc cmd/command pour afficher l'utilisation de chaque commande, par exemple

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

Les paramètres de drapeau pris en charge par cmd/compile sont les mêmes que ceux pris en charge par gcflags mentionnés précédemment. La différence entre go tool compile et go build est que le premier est uniquement responsable de la compilation, et ne peut prendre que des fichiers comme paramètres, le second peut prendre des répertoires, des packages, des fichiers comme paramètres, et ne fait pas que compiler le code source, il est également responsable de la liaison des fichiers, de la suppression des fichiers inutiles, etc., le premier fait partie du second. Nous pouvons afficher les commandes exécutées pendant le processus build

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

Dans le processus, vous pouvez voir qu'il y a /golang/pkg/tool/windows_amd64/compile.exe, qui appelle le compilateur. En plus de compile, il y a beaucoup d'autres outils qui peuvent être appelés, beaucoup de commandes go sont en fait leurs alias.

clean

La commande clean est utilisée pour supprimer les fichiers objets générés pendant le processus de compilation

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

Elle prend en charge les drapeaux suivants

  • -i : Supprime les fichiers archive ou binaires correspondants
  • -n : Affiche les commandes à exécuter pour le processus de nettoyage mais ne les exécute pas réellement
  • -x : Affiche les commandes à exécuter pour le processus de nettoyage et les exécute
  • -r : Nettoie récursivement via import path
  • -cache, supprime tout le cache généré par go build
  • -testcache : Supprime tout le cache de test généré
  • -modcache : Supprime tout le cache de modules téléchargés
  • -fuzzcache : Supprime le cache généré par fuzz test.

Lors de l'utilisation de go tool compile, c'est un appel direct à la commande du compilateur, et ne fait pas beaucoup de traitement postérieur comme go build, ce qui génère des fichiers objets. Par exemple, exécutez la commande suivante

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

Cela générera un fichier nommé main.o, utilisez la commande go clean pour le supprimer. Ou utilisez le paramètre -n pour afficher les commandes à exécuter.

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

Supprime le cache de compilation, il supprimera le cache de compilation généré dans le répertoire GOCACHE

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

Supprime le cache généré par fuzz test, ces caches sont stockés par défaut dans le répertoire GOCACHE/fuzz/

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

fix

Le langage go a maintenant dix ans depuis la rédaction de cet article, dans le processus de mise à jour et de modification continue du langage, il est inévitable qu'il y ait des incompatibilités dues aux changements d'API, la commande fix est conçue pour cela, elle détecte les API obsolètes dans les fichiers source et les remplace par de nouvelles API.

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

Elle prend en charge les répertoires, les noms de fichiers, les répertoires comme paramètres, accepte le drapeau -fix pour transmettre des paramètres afin d'indiquer quel type de modification effectuer, vous pouvez utiliser la commande go tool fix -help pour afficher les valeurs disponibles

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.

Voici un exemple, le code source utilise le package golang.org/x/net/context

sh
package main

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

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

Utilisez go fix pour corriger, en le remplaçant par le package context de la bibliothèque standard, vous pouvez utiliser la commande suivante pour effectuer le remplacement

sh
$ go fix -fix context main.go

Vous pouvez également ne pas remplacer, et voir les changements de fichier avant et après.

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

Le langage go existe depuis plus de dix ans et n'a que neuf paramètres de remplacement disponibles, ce qui montre que la compatibilité est plutôt bien maintenue.

fmt

La commande fmt est l'outil de formatage intégré de go, utilisé pour formater les fichiers source go.

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

Utilisez la commande go doc gofmt pour afficher sa documentation détaillée

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 utilise des tab pour l'indentation, des espaces pour l'alignement, par défaut le code formaté sera affiché sur la sortie standard, et non écrasé sur le fichier original. La commande go fmt utilise en fait la commande gofmt, qui est un fichier binaire indépendant, situé dans le répertoire GOROOT/bin.

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

Ajoutez le drapeau -n à la commande go fmt pour savoir quelles commandes seront exécutées.

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

On peut voir que go fmt est en fait un alias de gofmt -l -w, la commande gofmt dispose des paramètres suivants

  • -d : Affiche les différences de fichier avant et après le formatage
  • -e : Affiche toutes les erreurs
  • -l : Affiche les noms de fichiers qui ont été modifiés
  • -r : Applique les règles de formatage
  • -s : Tente de simplifier le code
  • -w : Écrase le fichier source, restaure la sauvegarde en cas d'erreur

Supposons maintenant que nous ayons le fichier source suivant

go
$ cat main.go
package main

import "fmt"

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

Utilisez le paramètre -d pour prévisualiser les changements

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

Le paramètre -l affichera les noms de fichiers qui seront modifiés

$ gofmt -l .
main.go

S'il y a des erreurs de syntaxe, le paramètre -e peut afficher plus de détails

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 appliquera les modifications au fichier source

sh
$ gofmt -l -w .
main.go

$ cat main.go
package main

import "fmt"

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

Vous pouvez constater qu'en tant qu'outil de formatage, gofmt ne fournit aucune configuration personnalisée, tandis que le formateur prettify dédié à l'embellissement du code js fournit un nombre considérable de configurations pour formater le code, cela reflète l'attitude de go officiel, ne voulez pas de personnalisation, le style de code de tout le monde ferait mieux d'être cohérent, au moins il y a un avantage, c'est que vous n'avez pas à vous adapter aux habitudes des autres lors de la lecture de code. Mais en fait, il conserve toujours un élément personnalisable, qui est les règles de remplacement du code formaté, les règles peuvent être personnalisées, le format est le suivant

pattern -> replacement

Par exemple, supprimer les parenthèses redondantes

(a) -> a

Afficher les changements de fichier

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

Vous pouvez voir que gofmt supprimera les parenthèses redondantes.

get

La commande get est absolument la plus couramment utilisée dans le développement go, son rôle est de télécharger le code source du package spécifié dans le répertoire correspondant à GOMODCACHE.

sh
$ go get -h
usage: go get [-t] [-u] [-v] [build flags] [packages]
Run 'go help get' for details.
  • -u : Tente de mettre à jour les versions mineures et les versions de correctifs du package, si cela implique un changement de version majeure, comme v1->v2, ne sera pas mis à jour.
  • -t : Met à jour les versions des dépendances dans les tests
  • -v : Affiche les packages compilés, fait en fait partie des paramètres de build flags

Dans les temps anciens, go get avait un rôle similaire à go install, il téléchargeait et compilait ces packages, cependant avec la naissance et l'amélioration des modules go, cette partie du rôle a progressivement été abandonnée, la commande get est maintenant le plus souvent utilisée pour télécharger et résoudre les dépendances des modules go, donc vous pouvez voir que la commande go get prend également en charge les drapeaux de construction de type build flags, et si vous essayez d'utiliser go get en dehors d'un module comme vous utiliseriez go install, il vous indiquera que cette utilisation est obsolète.

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

Pourquoi ces descriptions sont conservées dans la documentation est inconnu, en parcourant le code source de la commande get, vous découvrirez également qu'elle conserve les anciens drapeaux.

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
)

Pour en revenir au sujet, la commande get téléchargera le code source du package spécifié dans le répertoire de dépendances global local, c'est-à-dire le répertoire correspondant à GOCACHE, puis enregistrera les informations dans les fichiers go.mod et go.sum, le premier est responsable de l'enregistrement de la version, le second est responsable de l'enregistrement de la somme de contrôle sha1 pour assurer la sécurité. La commande get est en fait basée sur VCS, c'est-à-dire le système de contrôle de version local, prend en charge les suivants au total

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

Parmi eux, par défaut, seuls git et hg sont pris en charge, peuvent être configurés dans GOVCS, le format est le suivant

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

GOVCS prend uniquement en charge git et hg en tant que VCS, les trois autres doivent être configurés dans GOPRIVATE.

La commande go get a au total les utilisations suivantes, peut directement utiliser l'adresse de dépendance comme paramètre

sh
$ go get golang.org/x/net

Peut également spécifier une version

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

Spécifier la dernière version

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

Tenter de mettre à jour la version

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

Supprimer une dépendance

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

Ce qui précède est utilisé pour gérer les dépendances ordinaires, elle peut également être utilisée pour gérer des dépendances moins ordinaires, comme mettre à jour la version du langage go

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

Peut même être utilisée pour mettre à jour la version de la chaîne d'outils go

sh
$ go get toolchain@latest

Lorsque vous utilisez go get pour mettre à jour les versions de go et de la chaîne d'outils, elles installeront la nouvelle version de go dans le répertoire GOMODCACHE/golang.org/

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

Ensuite, modifiez manuellement GOROOT pour passer à la version spécifiée.

install

La commande install est similaire à la commande get, elles sont toutes deux utilisées pour télécharger des dépendances tierces, mais la différence est que la commande get télécharge le code source, tandis que la commande install compile le code source en un fichier binaire exécutable pour la machine locale, le chemin de stockage du fichier binaire est d'abord dans le répertoire GOBIN, puis GOPATH/bin. La fonction principale de cette commande est de télécharger des outils en ligne de commande publics tiers, grâce à la vitesse de compilation et à la portabilité du langage go, il n'est pas nécessaire de télécharger des fichiers binaires, mais de télécharger directement le code source puis de le compiler localement.

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

La commande install accepte les drapeaux de construction et les noms de packages comme paramètres, avec gomod activé, le nom du package doit inclure un numéro de version. Par exemple, télécharger le débogueur delve

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/

Elle téléchargera d'abord le code source dans le chemin de stockage de GOMODCACHE, ce qui est cohérent avec la commande get, puis passera au répertoire de travail temporaire, le compilera, après la compilation, déplacera le fichier binaire dans le répertoire GOPATH/bin, et enfin supprimera le répertoire temporaire. La commande install a également une limitation, c'est que le package téléchargé doit être le package d'entrée du projet, c'est-à-dire qu'il doit contenir le fichier d'entrée main.go, sinon il vous indiquera qu'il ne peut pas être installé. Par exemple, utilisez go install pour télécharger gin

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 est une bibliothèque de dépendances de framework web, ce n'est pas un outil en ligne de commande, donc naturellement il n'y a pas de fichier d'entrée, donc l'installation échouera.

list

La commande list liste les packages à l'emplacement spécifié, un par ligne, et prend en charge la sortie formatée personnalisée, prend en charge de nombreux paramètres, la condition préalable à son utilisation est qu'elle doit être dans un projet qui prend en charge gomod.

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

Les paramètres qu'elle prend en charge sont les suivants

  • -f : Paramètre de formatage
  • -json : Sortie au format json
  • -compiled : Affiche tous les packages qui seront compilés par le compilateur
  • -deps : Affiche chaque package et le nom de chaque package dont il dépend
  • -test : Affiche le package de test de chaque package
  • -e : Affiche normalement lors de la rencontre de packages erronés
  • -find : N'analyse pas les relations de dépendance de ces packages
  • -export : Lors de l'utilisation de ce paramètre, définit la valeur du champ Package.Export de la structure sur le fichier contenant les informations d'exportation les plus récentes du package spécifié, et définit la valeur du champ Package.BuildID sur le BuildID du package, principalement utilisé pour la sortie formatée.

Paramètres d'informations de module,

  • -m : Affiche les modules au lieu des packages

  • -versions : Affiche toutes les informations disponibles d'un module

  • -retracted : Affiche les versions retirées d'un module

Le paramètre [packages] peut être un nom de package spécifié, ou un répertoire, ou all, qui signifie n'importe où, lors de l'utilisation du paramètre -m, all signifie toutes les dépendances référencées par le module actuel.

Par exemple, le fichier actuel contient uniquement un fichier main.go, et contient uniquement une ligne de code qui affiche "hello world", après l'exécution de go list -deps ., il affiche tous les packages dépendants depuis le projet actuel jusqu'à fmt et ses références.

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

Ou affiche toutes les dépendances de module du projet actuel

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

La sortie de la commande list est par ligne, chaque ligne de sortie est un package. L'officiel fournit un paramètre -f qui nous permet de personnaliser le format de sortie de ligne, la valeur qu'il accepte est la syntaxe de modèle définie par le package de moteur de modèle template/text, par exemple

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

Chaque package itéré sera transmis sous la forme de la structure suivante, tous les champs de cette structure peuvent être utilisés comme paramètres de modèle.

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
}

Si l'itération concerne des modules, ils seront transmis sous la forme de la structure suivante, tous ses champs peuvent également être utilisés comme paramètres de modèle.

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
}

Afficher tous les packages

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

Afficher les modules

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

mod

go mod est une commande dédiée à la gestion des modules go.

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.

Elle dispose des sous-commandes suivantes

  • download : Télécharge toutes les dépendances indiquées dans le fichier go.mod dans le cache local
  • edit : Modifie le fichier go.mod, l'interface de ligne de commande fournie est principalement destinée à être appelée par d'autres outils ou scripts.
  • init : Initialise un projet gomod dans le répertoire actuel
  • tidy : Télécharge les dépendances manquantes, supprime les dépendances inutiles
  • graph : Affiche le graphique des dépendances
  • verify : Vérifie les dépendances locales
  • why : Explique pourquoi ces modules sont dépendants
  • vendor : Exporte les dépendances du projet vers le répertoire vendor

init

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

La commande init est utilisée pour initialiser un projet gomod, son seul paramètre est le chemin du module, si quelqu'un veut télécharger vos dépendances à l'avenir, il devra utiliser ce chemin de module comme base. Sa règle de nommage est généralement

domain_name/user_name/repo_name

Par exemple, comme tout le monde met généralement ses projets sur github, cela peut être

github.com/jack/gotour

Il est déconseillé d'utiliser des caractères spéciaux comme chemin de module. Voici un cas d'utilisation

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]

La commande tidy supprimera les dépendances inutiles de go.mod, c'est-à-dire les dépendances qui ne sont pas référencées, et téléchargera les dépendances qui sont référencées mais qui n'existent pas. Elle prend en charge les paramètres suivants

  • -v, affiche les dépendances de module supprimées
  • -e, ignore les erreurs si elles se produisent pendant le processus et continue l'exécution
  • -x, affiche le processus d'exécution
  • -go=version, met à jour la version go dans le fichier go.mod
  • -compat=version, conserve toutes les sommes de contrôle supplémentaires requises de la version Go principale spécifiée pour charger le graphique de modules avec succès, et si la commande go de cette version charge tout package importé à partir de différentes versions de modules, cela entraînera une erreur tidy. Ce paramètre est rarement utilisé, généralement des erreurs se produisent uniquement lors des changements de version, vous pouvez consulter cette réponse sur stackoverflow go modules - go mod tidy error message: "but go 1.16 would select" - Stack Overflow

Voici un exemple d'utilisation

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]

Bien que le nom de la commande download se traduise par télécharger, elle ne fait que télécharger les dépendances dans le cache de dépendances local, ne modifie pas le fichier go.mod, son rôle est de pré-télécharger les dépendances dans le cache de fichiers local, si vous souhaitez télécharger une dépendance spécifique, il est recommandé d'utiliser go get ou go mod tidy.

Voici quelques exemples d'utilisation

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)

Sans aucun paramètre, elle téléchargera toutes les dépendances qui existent dans le fichier go.mod mais qui n'existent pas dans le cache de dépendances local, s'il n'y a rien à télécharger, elle affichera

go: no module dependencies to download

edit

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

edit est une interface de ligne de commande utilisée pour modifier le fichier go.mod, généralement fournie à d'autres programmes, certains éditeurs IDE utiliseront ces commandes pour fournir un support gomod. Elle prend en charge les paramètres suivants

  • -module, modifie le chemin du module
  • -go=version, modifie la version go attendue
  • -require=path@version, ajoute une dépendance
  • -droprequire=path@version, supprime une dépendance
  • -exclude=path@version, ajoute une dépendance exclue
  • -dropexclude=path@version, supprime une dépendance exclue
  • -replace=old@version=new@version, ajoute une dépendance de remplacement
  • -dropreplace=old@version, supprime une dépendance de remplacement
  • -retract=version, ajoute un élément de rétraction de version
  • -dropretract=version, supprime un élément de rétraction de version

Il y a aussi d'autres paramètres utilisés pour l'affichage

  • -print, affiche le contenu du fichier
  • -json, affiche au format json

Par exemple

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

La commande graph affichera le graphique des dépendances du projet actuel, sa lisibilité est très mauvaise, et la plupart du temps n'est pas destinée à être lue par des humains, les résultats sont généralement traités puis affichés sous forme visualisée. Chaque ligne est une dépendance, le format est le suivant

Référence  Référencé

Par exemple

golearn go@1.21.3

Elle prend également en charge deux paramètres

  • -go=version, charge le graphique des dépendances avec la version go donnée, sa valeur ne peut pas être inférieure à la version dans le fichier go.mod.
  • -x, affiche les commandes exécutées pendant le processus.

Voici un exemple d'utilisation simple

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 est une alternative à gopath avant le lancement de gomod, chaque projet go aura un répertoire vendor, stockant les dépendances de chaque projet séparément selon le format domain/user/project, tout comme le node_module volumineux de nodeJs, les dépendances de chaque projet sont stockées séparément, cette méthode de gestion des dépendances semble vraiment stupide maintenant, mais à cette époque il n'y avait vraiment pas de meilleure solution, la raison pour laquelle vendor est conservé est parce que go adhère à l'engagement de rétrocompatibilité, certains anciens projets y compris le code source de go peuvent encore utiliser vendor.

Pour en revenir au sujet, vendor est une sous-commande de go mod, elle peut exporter les dépendances globales référencées par le module actuel vers le répertoire vendor.

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

Elle dispose des paramètres suivants

  • -o : Spécifie le chemin du répertoire de sortie
  • -v : Affiche chaque dépendance
  • -e : Ne quitte pas en cas d'erreur et continue

Voici un exemple, utilisez d'abord go list -m all pour voir les dépendances référencées par le projet actuel

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

Exportez vers le répertoire vendor actuel

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

La structure du répertoire après exportation est la suivante

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

Le fichier modules.txt est un fichier qui décrit tous les éléments de dépendance, similaire au go.mod actuel.

verify

sh
$ go help mod verify
usage: go mod verify

Cette commande vérifiera si les dépendances du projet ont été modifiées après avoir été téléchargées localement. Par exemple, s'il n'y a pas de problème, elle affichera all modules verified

sh
$ go mod verify
all modules verified

Sinon, elle signalera où des changements se sont produits, et terminera la commande avec un état anormal. Par exemple

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

Explique pourquoi ce package est dépendant, affiche en fait le graphique des dépendances à son sujet. Par exemple

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

Par défaut, analysera uniquement les importations depuis main, ajoutez le paramètre -m pour analyser la situation d'importation de chaque package.

work

La commande work est un outil de développement local pour la gestion multi-modules go

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

La sous-commande init est utilisée pour initialiser un workspace, cette commande créera un fichier nommé go.work

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

Accepte le paramètre [moddirs] pour spécifier quels modules inclure dans la gestion, par exemple

bash
$ go work init ./service ./api

use

La sous-commande use est utilisée pour ajouter des répertoires de modules gérés à 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.

Accepte [moddirs] comme paramètre, et un -r pour rechercher récursivement des modules dans le chemin [moddirs], par exemple

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

edit

Le rôle de la sous-commande edit est le même que go mod edit, toutes deux sont laissées à l'interface de ligne de commande pour que d'autres outils et scripts les utilisent.

$ 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

Les paramètres sont les suivants

  • -fmt, formate le fichier go.work

  • -use, -dropuse, ajoute et supprime des chemins de modules

  • -replace=old[@v]=new[@v], -dropreplace=old[@v]=new[@v], utilisés pour ajouter et supprimer des modules à remplacer

  • -go, -toolchain=name, spécifie la version go, et spécifie la chaîne d'outils à utiliser

  • -print, affiche les modifications finales, ne les réécrit pas dans le fichier

  • -json, affiche au format json, ne peut pas être utilisé avec -print, la structure de type correspondante est la suivante

    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
    }

Voici quelques exemples d'utilisation, sortie formatée

bash
$ go work edit -fmt -print
go 1.22.0

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

Sortie json

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

sync

La sous-commande sync est utilisée pour synchroniser la liste des modules dans go.work vers les différents modules du workspace.

bash
$ go help work sync
usage: go work sync

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

Ce processus se produit principalement après le développement local terminé, chaque module a terminé le travail de publication, à ce moment, utilisez sync, il mettra à jour les dépendances dans go.mod de tous les modules du workspace en fonction des relations de dépendance de chaque module, nous évitant ainsi de mettre à jour manuellement.

vendor

La commande vendor copiera toutes les bibliothèques de dépendances de modules dans le workspace vers le répertoire vendor.

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

Fonctionne de la même manière que go mod vendor, donc je ne vais pas trop m'étendre.

vet

La commande vet est un outil de vérification statique des erreurs du code source go, tout comme les outils lint d'autres langages, comme 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.

Prenons d'abord un exemple simple, voici le code source suivant

sh
$ cat main.go
package main

import "fmt"

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

Exécutez go vet sans aucun paramètre dans le même répertoire

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

vet signalera quel fichier, quelle ligne et quel problème. Elle prend en charge les drapeaux de construction comme paramètres, tels que -n et -x, prend en charge les packages, les répertoires, les noms de fichiers comme paramètres.

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

Utilisez la commande suivante pour afficher ses paramètres et explications plus détaillés.

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

La commande go tool vet ne peut pas être utilisée directement pour vérifier le code, vous devez utiliser go vet. Le paramètre [vet flag] de go vet prend en charge la définition des analyseurs de code, les valeurs disponibles sont les suivantes

asmdecl      Vérifie si les fichiers assembleur correspondent aux déclarations go
assign       Vérifie s'il y a des affectations inutiles
atomic       Vérifie si l'atomicité est violée lors de l'utilisation de sync/atomic
bools        Vérifie une utilisation incorrecte des opérateurs logiques
buildtag     Vérifie les build tags
cgocall      Vérifie les violations des règles de passage de pointeurs cgo
composites   Vérifie les structures composites non initialisées, comme map, chan
copylocks    Vérifie s'il y a une copie de valeur de verrou
directive    Vérifie les instructions de la chaîne d'outils go
errorsas     Vérifie si des types non pointeurs ou non error sont passés à errors.As
framepointer Vérifie si le code assembleur optimisé par compilation efface le pointeur de trame avant de le sauvegarder
httpresponse Vérifie une utilisation incorrecte de httpresponse
ifaceassert  Vérifie les assertions de type d'interface à interface
loopclosure  Problèmes de référence des variables de boucle
lostcancel   context.WithCancel n'utilise pas la fonction cancel
nilfunc      Vérifie s'il y a des comparaisons inutiles entre fonction et nil
printf       Vérifie si les paramètres de formatage printf sont corrects
shift        Vérifie s'il y a des décalages égaux ou supérieurs à la largeur des entiers
sigchanyzer  Vérifie les chan os.Signal non tamponnés
slog         Vérifie les appels de journalisation structurée illégaux
stdmethods   Vérifie si les signatures des méthodes d'interface connues sont correctes
stringintconv Vérifie la conversion de chaînes en entiers
structtag    Vérifie si les tags de structure sont corrects
testinggoroutine Vérifie si les协程 utilisent testing.Fatal dans les tests
tests        Vérifie les utilisations courantes erronées des tests et exemples
timeformat   Vérifie si le format de temps utilisé avec (time.Time).Format ou time.Parse est correct
unmarshal    Passe des types non pointeurs ou non interface à unmarshal
unreachable  Vérifie le code inaccessible
unsafeptr    Vérifie les conversions incorrectes de uintptr en unsafe.Pointer
unusedresult Vérifie les valeurs de retour de fonction non utilisées

Ce sont tous des analyseurs qui analysent un point spécifique, par exemple l'analyseur timeformat vérifie si le format d'appel de time.Format est conforme à la syntaxe correcte. Par défaut, tous les analyseurs ci-dessus sont activés, pour en activer un seul, utilisez le format suivant

sh
$ go vet -timeformat main.go

Désactiver un seul

sh
$ go vet -timeformat=false main.go

Le code source de ces analyseurs est situé dans cmd/vendor/golang.org/x/tools/go/analysis/passes, chaque analyseur est un piège facile dans le langage go, il est donc fortement recommandé d'utiliser la commande vet pour vérifier votre code. En plus de cela, elle prend également en charge d'autres paramètres de drapeau

  • -V, affiche uniquement la version puis quitte
  • -json, affiche au format json
  • -c=n, affiche le nombre spécifié de lignes de conflit dans le contexte (ne semble avoir aucun effet)

Il y a aussi des analyseurs externes, comme shadows, qui est responsable de la détection des problèmes de masquage de variables avec des noms de variables courts, comme il est externe, il doit être téléchargé avec go install

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

Utilisez le format suivant

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.

La commande test est la commande qui fournit la fonctionnalité de test dans la chaîne d'outils du langage go, cette fonctionnalité est très importante, pour un logiciel, des tests complets sont indispensables. Ici, je vais simplement présenter brièvement comment utiliser la commande test, si vous souhaitez en savoir plus sur les tests, rendez-vous sur : Tests

En plus de prendre en charge les paramètres de compilation de la commande build, test prend également en charge les paramètres suivants

  • -args, paramètres d'entrée du programme
  • -c, compile le fichier binaire de test du package actuel dans le répertoire actuel mais ne l'exécute pas, nommé pkg.test
  • -exec, exécute d'autres commandes avant le début du test
  • -json, le style de sortie du test devient json
  • -o, spécifie le chemin du fichier binaire de test

Elle prend également en charge de nombreux testflag, utilisez la commande help pour afficher tous les testflag

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

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

Présentation de quelques-uns couramment utilisés

  • -v, affiche les résultats de test de chaque cas.
  • -timeout duration, temps d'exécution maximal du test
  • -skip regexp, saute les cas de test spécifiés
  • -short, réduit le temps d'exécution des cas de test qui prennent beaucoup de temps
  • -shuffle, mélange l'ordre d'exécution de tous les cas de test
  • -run regexp, exécute les cas de test spécifiés
  • -list regexp, liste chaque cas de test
  • -cpu 1,2,4, spécifie le nombre de cpu
  • -count n, spécifie combien de fois chaque cas de test doit être exécuté

L'utilisation la plus simple est, sans aucun paramètre, elle exécutera tous les cas de test du package actuel et affichera les résultats.

sh
$ ls *_test.go
hello_test.go

$ go test
PASS
ok      golearn 0.522s

Spécifier un fichier de test

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

Ajoutez le paramètre -v pour afficher une sortie plus détaillée, c'est très couramment utilisé.

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

Spécifier un cas de test

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

Lors des tests, la commande test dispose de deux modes, parlons d'abord du mode répertoire, lorsque la commande test est exécutée sans le paramètre package, elle exécutera les tests en mode répertoire, par exemple les commandes suivantes

sh
$ go test
$ go test -v

Dans ce mode, le cache de test est désactivé. L'autre mode est le mode liste, lorsque le paramètre package n'est pas vide, les tests seront exécutés en mode liste, la différence avec le premier est que le cache de test est activé ou non. Par exemple

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

En mode liste, go compilera et exécutera les fichiers de test de chaque package sous le package spécifié en fichiers binaires, pour éviter d'exécuter les tests à plusieurs reprises, go mettra par défaut les résultats en cache, et ne recompilera pas lors de la deuxième exécution. Le cache sera activé par défaut lors de l'utilisation des paramètres suivants

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

Utiliser d'autres paramètres que ceux-ci permettra de désactiver le cache, la méthode recommandée par l'officiel est d'utiliser -count=1 pour désactiver le cache. Par exemple

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

Instructions

Contrairement aux commandes, les instructions go existent sous forme codée en dur dans les fichiers source, elles ont un autre nom plus technique : directives de compilation (pragma directives).

Les compilateurs et les éditeurs de liens modifieront leur propre comportement en raison d'elles afin d'atteindre le contrôle de la compilation, un peu comme les macros dans le langage C, bien sûr, toutes les instructions ne sont pas utilisées pour affecter la compilation, certaines sont utilisées pour d'autres comportements fonctionnels, par exemple l'instruction generate est généralement utilisée pour la fonctionnalité de génération de code. Ces instructions existent généralement sous forme de commentaires, et ont le préfixe //go:, sans aucun espace au milieu, par exemple l'instruction //go:generate. Tous les types d'instructions sont divisés en deux catégories

  • Instructions fonctionnelles, ce sont des instructions fonctionnelles fournies par go qui peuvent être utilisées librement, comme generate, embed, build.
  • Instructions du compilateur, ces instructions doivent être utilisées avec prudence, une utilisation abusive peut entraîner des résultats imprévisibles.

À l'exception des instructions fonctionnelles, la plupart des instructions ne peuvent agir que sur les signatures de fonctions. Pour les instructions du compilateur, vous pouvez exécuter la commande go doc compile pour afficher leurs instructions. Pour toutes les instructions, vous pouvez trouver des informations à leur sujet dans 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]

L'instruction generate comme son nom l'indique est liée à la génération, généralement son rôle est d'exécuter des commandes qui génèrent du code et mettent à jour le code source, mais en réalité elle peut exécuter n'importe quelle commande. Et, l'instruction generate est différente des autres instructions, elle dispose d'une commande dédiée pour exécuter toutes les instructions generate situées dans les fichiers source. Elle peut utiliser des noms de fichiers ou des noms de packages comme paramètres d'entrée pour indiquer quels fichiers exécuter les instructions generate, voici ses autres paramètres.

  • -run=regex, exécute les instructions generate spécifiées
  • -skip=regex, saute les instructions generate spécifiées
  • -n, affiche les commandes qui seront exécutées
  • -x, affiche les commandes exécutées pendant le processus
  • -v, affiche les fichiers traités

En outre, les commandes exécutées dans l'instruction generate prennent également en charge les paramètres intégrés suivants

  • $GOARCH, architecture cpu
  • $GOOS, système d'exploitation
  • $GOFILE, nom de fichier
  • $GOLINE, numéro de ligne
  • $GOPACKAGE, nom du package
  • $GOROOT, go root
  • $DOLLAR, symbole dollar
  • $PATH, variable d'environnement path

Prenons un exemple, pas de code, juste une ligne de commentaire

go
package main

//go:generate echo "hello world!"

Exécutez la commande

$ go generate .
hello world!

Cet exemple exécute une commande go

go
package main

//go:generate go version

Exécutez la commande

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

L'instruction generate peut être utilisée pour exécuter n'importe quelle commande, comme swagger pour générer de la documentation API, ou Wire pour générer du code IOC. Cependant, cette instruction ne convient pas pour exécuter des commandes trop complexes, elle convient pour exécuter des commandes courtes, s'il y a des besoins complexes, vous pouvez utiliser des scripts ou makefile à la place.

embed

L'instruction embed est une nouvelle fonctionnalité ajoutée en 1.16, son rôle est d'emballer des fichiers statiques dans le fichier binaire, comme des modèles HTML, etc. Son format est le suivant

go
//go:embed pattern

pattern peut être une expression glob, un répertoire ou un fichier spécifique. Prenons un exemple

go
package main

import "embed"

//go:embed *
var static embed.FS

L'instruction embed doit être située au-dessus d'une variable globale de type embed.Fs, notez qu'elle doit être une variable globale, et son utilisation nécessite d'importer le package embed, dans cet exemple, * représente que tous les fichiers du répertoire actuel seront emballés dans le fichier binaire, mais elle n'autorisera pas les répertoires commençant par ..

L'exemple suivant montre comment lire le contenu à partir de fichiers intégrés

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

Il n'a que trois méthodes, l'utilisation n'est pas différente d'un système de fichiers normal, et comme il implémente l'interface io/Fs, il peut également être transmis en tant qu'objet Fs.

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)

L'exemple suivant montre comment intégrer des fichiers html via l'instruction embed, et y accéder via un service http.

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

Le résultat d'accès est le suivant

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>

L'instruction embed prend également en charge le type de variable globale []byte, par exemple

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

L'effet réalisé est similaire à l'exemple précédent.

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

Dans la section build-Contrôle de compilation, nous avons parlé de l'utilisation de l'instruction // +build pour contrôler le comportement de compilation. L'instruction //go:build est une nouvelle fonctionnalité ajoutée en 1.17, destinée à remplacer l'instruction précédente, mais maintenant en 1.21 elle n'a pas encore été remplacée, elle existera probablement de manière coexistante à l'avenir, à propos de cette nouvelle instruction, la documentation officielle présente également une introduction : build constraints. Sa fonction n'est pas très différente de la précédente, mais la syntaxe est plus stricte, prend en charge les expressions booléennes, prenons un exemple

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

package pkg_name

Cette méthode est beaucoup plus lisible que l'ancienne.

line

L'instruction line affectera le numéro de ligne, le numéro de colonne et le nom de fichier de la ligne suivante, son rôle se limite à cela, la plupart du temps elle peut être utilisée pour déboguer des erreurs, etc. Par exemple, en cas d'erreur, elle modifiera les informations de sortie du compilateur.

go
package main

var a undefinedType

func main() {

}

Normalement, le compilateur affichera

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

Mais si l'instruction line est utilisée, c'est différent

go
package main

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

func main() {

}

Alors la sortie sera

abc.go:10:106: undefined: undefinedType

Et en raison de raisons historiques, l'instruction line est également la seule instruction dont l'utilisation est différente des autres instructions. Son format est

go
//line filename:line:column

Vous pouvez voir qu'elle n'a pas besoin de go: comme préfixe.

linkname

Cette instruction peut être utilisée pour lier des fonctions ou des variables globales d'autres packages, même s'il s'agit de types privés, cette opération apparaît souvent dans la bibliothèque standard, en particulier dans runtime, certaines fonctions n'ont pas de corps de fonction et sont implémentées de cette manière, une autre partie des fonctions avec un corps de fonction vide est implémentée en assembleur. Voyons son utilisation, le format d'utilisation est le suivant

go
//go:linkname nom_lié type_lié

Et avant utilisation, par exemple importez le package unsafe. Prenons un exemple simple de liaison d'un type privé dans la bibliothèque standard

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

Sortie

15395306441938000233

Elle lie la fonction privée runtime.memhash à la fonction que nous avons déclarée, cette fonction n'a pas de corps de fonction, seulement une signature, sert uniquement de support. Le rôle de memhash est de calculer une somme de hachage en fonction de la mémoire, étant donné un pointeur, une graine de hachage et un décalage mémoire. Ce processus de liaison est effectué pendant la compilation,

Si ce n'est pas la bibliothèque standard, la situation est quelque peu différente, par exemple, il y a une fonction test dans le package example, avant la liaison, vous devez d'abord importer anonymement ce package.

go
package example

// Un type privé, inaccessible de l'extérieur.
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())
}

Sortie

a

Vous pouvez voir que la liaison a réussi, cette méthode peut contourner le système de modules go pour faire ce que vous voulez, mais il n'est pas recommandé de l'utiliser à grande échelle, à moins que vous ne sachiez ce que vous faites.

noinline

L'instruction noinline indique qu'une fonction est interdite d'optimisation d'inlining, même si elle est très simple. Prenons un exemple simple

go
package main

func val() string {
  return "val"
}

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

val est une fonction très simple, son rôle est de retourner un littéral de chaîne, comme elle est trop simple et que le résultat est toujours prévisible, alors lors de la compilation elle sera optimisée par le compilateur sous la forme suivante

go
package main

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

Voyons à quoi ressemble son assembleur, vous pouvez voir qu'il n'y a pas d'appel à la fonction val.

TEXT    main.val(SB), NOSPLIT|NOFRAME|ABIInternal, $0-0
FUNCDATA        $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
FUNCDATA        $1, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
LEAQ    go:string."val"(SB), AX
MOVL    $3, BX

FUNCDATA        $0, gclocals·g2BeySu+wFnoycgXfElmcg==(SB)
RET

Ensuite, ajoutez l'instruction noinline

go
package main

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

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

Voyons maintenant sa forme assembleur

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

Cette fois, vous pouvez voir très clairement l'appel main.val, et c'est exactement la fonction de l'instruction noinline, empêcher l'inlining de fonction lors de l'optimisation du compilateur.

nosplit

L'instruction nosplit sert à sauter la détection de débordement de pile. Comme le modèle de planification concurrente de go est une planification préemptive, supposons qu'une fonction exécutera du code très bas niveau, d'autres coroutines qui appellent cette fonction ne sont pas adaptées pour être préemptées, vous pouvez utiliser cette instruction pour l'indiquer.

go
//go:nosplit
func nosplitFn()

Après avoir utilisé cette instruction, il n'y aura plus de croissance de pile.

noescape

noescape, comme son nom l'indique facilement, est lié à l'échappement, son rôle est d'indiquer que la fonction actuelle n'effectuera pas de comportement d'échappement mémoire, après l'exécution toutes les ressources sont récupérées, et cette fonction ne doit avoir qu'une signature sans corps de fonction, dans ce cas, l'implémentation de la fonction est généralement réalisée en assembleur.

Par exemple, memhash utilisé précédemment utilisera cette instruction

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

De cette façon, le compilateur n'effectuera pas d'analyse d'échappement, à condition que vous garantissiez qu'il n'y aura pas d'échappement, s'il y en a, alors on ne sait pas quelles seront les conséquences.

uintptrescapes

L'instruction uintptrescapes indique que les paramètres de type uintptr dans cette fonction sont convertis en valeurs de pointeur et s'échappent vers le tas, et doivent rester vivants. Cette instruction est généralement utilisée pour certains appels système de bas niveau, dans la plupart des cas, il n'est pas nécessaire de la comprendre.

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

Auparavant, il devrait y avoir eu une instruction notinheaps utilisée pour indiquer qu'un type n'est pas autorisé à allouer de la mémoire sur le tas, je ne sais pas dans quelle version elle a été supprimée.

norace

L'instruction norace indique que l'accès mémoire d'une fonction n'a plus besoin d'analyse de course, généralement utilisé lors de l'exécution de code de bas niveau qui ne convient pas à l'analyse de course.

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

TIP

Certaines instructions sont limitées à une utilisation par le package runtime uniquement, externes ne peuvent pas les utiliser, elles impliqueront des choses plus profondes, si vous souhaitez en savoir plus, vous pouvez voir leur introduction dans Runtime-only compiler directives.

Golang by www.golangdev.cn edit