Línea de Comandos

Los comandos de Go incluyen un conjunto completo de toolchain que cubren documentación, formateo, análisis de código, compilación, pruebas, gestión de dependencias y otros aspectos del desarrollo en Go.
bug reportar errores
build compilar paquetes y dependencias
clean eliminar archivos objeto
doc mostrar documentación del código fuente
env ver información de variables de entorno de Go
fix reparar problemas de compatibilidad de API causados por cambios de versión
fmt formatear código fuente
generate generación de código
get agregar dependencias
install instalar y compilar paquetes
list comando de lista de paquetes/módulos
mod comando de mantenimiento de módulos
work comando de mantenimiento de workspace
run compilar y ejecutar
test probar
tool ejecutar herramienta go especificada
version mostrar información de versión de Go
vet escanear y mostrar posibles problemas en el código fuenteEste artículo solo describe brevemente su uso, todo el contenido está referenciado de la documentación oficial, para más detalles puedes visitar cmd/go.
help
El primero que debes conocer es el comando help, a través de él puedes leer el uso de los comandos. Hay dos formas de usarlo, si quieres obtener información breve de uso, puedes agregar el flag -h después del comando especificado, por ejemplo
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.Go mostrará de forma concisa el uso de ese comando, también te indicará que para obtener información más detallada necesitas usar el comando help
$ go help env
usage: go env [-json] [-u] [-w] [var ...]
Env prints Go environment information.
By default env prints information as a shell script
(on Windows, a batch file). If one or more variable
names is given as arguments, env prints the value of
each named variable on its own line.
The -json flag prints the environment in JSON format
instead of as a shell script.
The -u flag requires one or more arguments and unsets
the default setting for the named environment variables,
if one has been set with 'go env -w'.
The -w flag requires one or more arguments of the
form NAME=VALUE and changes the default settings
of the named environment variables to the given values.
For more about environment variables, see 'go help environment'.Aprende a usar bien el comando help, a través de él puedes obtener mucha información sobre los comandos.
doc
$ go doc -h
Usage of [go] doc:
go doc
go doc <pkg>
go doc <sym>[.<methodOrField>]
go doc [<pkg>.]<sym>[.<methodOrField>]
go doc [<pkg>.][<sym>.]<methodOrField>
go doc <pkg> <sym>[.<methodOrField>]
For more information run
go help doc
Flags:
-C dir
change to dir before running command
-all
show all documentation for package
-c symbol matching honors case (paths not affected)
-cmd
show symbols with package docs even if package is a command
-short
one-line representation for each symbol
-src
show source code for symbol
-u show unexported symbols as well as exportedEl comando doc mostrará los comentarios de documentación del paquete, constante, función, tipo, variable, método e incluso campo de estructura especificado. Sin ningún parámetro, mostrará los comentarios del paquete actual
$ go docTambién puedes especificar ver un paquete determinado, por ejemplo ver los comentarios de documentación del paquete runtime
$ go doc runtime
package runtime // import "runtime"
Package runtime contains operations that interact with Go's runtime system,
such as functions to control goroutines. It also includes the low-level type
information used by the reflect package; see reflect's documentation for the
programmable interface to the run-time type system.
......O un tipo determinado
$ go doc unsafe.Pointer
package unsafe // import "unsafe"
type Pointer *ArbitraryType
Pointer represents a pointer to an arbitrary type. There are four special
operations available for type Pointer that are not available for other
types:
- A pointer value of any type can be converted to a Pointer.
- A Pointer can be converted to a pointer value of any type.
- A uintptr can be converted to a Pointer.
- A Pointer can be converted to a uintptr.
...O una función determinada
$ 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.Tiene los siguientes flags comúnmente usados
-u:ver tipos privados-all:ver toda la documentación del paquete especificado-short:solo una línea de descripción breve-src:mostrar el código fuente-cmd:para algunos paquetes que pertenecen a comandos go, también mostrar la documentación de código dentro del paquete.
Por ejemplo, ver la variable runtime.inf, esta es una variable que no se expone externamente
$ go doc -u runtime.inf
package runtime // import "runtime"
var inf = float64frombits(0x7FF0000000000000)Aprovechar bien el comando doc puede ayudarte a leer la documentación más fácilmente.
Otra forma de leer la documentación de comandos es leer el código fuente, porque la documentación de algunos comandos no está tan detallada, pero en el código fuente hay explicaciones más detalladas. Como todos estos comandos están escritos en go, leerlos también es bastante conveniente. Estos comandos están ubicados en el paquete src/cmd, cada subpaquete es un comando separado, la entrada está en el archivo cmd/go/main.go
func init() {
base.Go.Commands = []*base.Command{
bug.CmdBug,
work.CmdBuild,
clean.CmdClean,
doc.CmdDoc,
envcmd.CmdEnv,
fix.CmdFix,
fmtcmd.CmdFmt,
generate.CmdGenerate,
modget.CmdGet,
work.CmdInstall,
list.CmdList,
modcmd.CmdMod,
workcmd.CmdWork,
run.CmdRun,
test.CmdTest,
tool.CmdTool,
version.CmdVersion,
vet.CmdVet,
help.HelpBuildConstraint,
help.HelpBuildmode,
help.HelpC,
help.HelpCache,
help.HelpEnvironment,
help.HelpFileType,
modload.HelpGoMod,
help.HelpGopath,
get.HelpGopathGet,
modfetch.HelpGoproxy,
help.HelpImportPath,
modload.HelpModules,
modget.HelpModuleGet,
modfetch.HelpModuleAuth,
help.HelpPackages,
modfetch.HelpPrivate,
test.HelpTestflag,
test.HelpTestfunc,
modget.HelpVCS,
}
}Aquí encontrarás todos los subcomandos de go y su información de documentación de ayuda.
bug
$ go help bug
usage: go bug
Bug opens the default browser and starts a new bug report.
The report includes useful system information.Este comando no tiene ningún parámetro ni flag, abrirá tu navegador predeterminado para visitar la interfaz de issues del repositorio github.com/golang/go, facilitándote reportar bugs, aparte de eso no tiene ninguna otra función.
version
A través del comando version puedes ver la información de versión actual de go.
$ go version -h
usage: go version [-m] [-v] [file ...]Sin ningún parámetro, mostrará la versión actual del lenguaje go
$ go version
go version go1.21.0 windows/amd64También acepta rutas de archivo como parámetro, mostrará la versión de go usada al compilar todos los archivos binarios reconocibles en esa ruta.
$ 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.0El parámetro -v indica al comando version que intente mostrar la versión de go de archivos que no se pueden reconocer, el parámetro -m muestra información de módulos del archivo binario y algunos parámetros de compilación, aquí hay un ejemplo simple.
$ go version -v -m wire.exe
wire.exe: go1.21.0
path github.com/google/wire/cmd/wire
mod github.com/google/wire v0.5.0 h1:I7ELFeVBr3yfPIcc8+MWvrjk+3VjbcSzoXm3JVa+jD8=
dep github.com/google/subcommands v1.0.1 h1:/eqq+otEXm5vhfBrbREPCSVQbvofip6kIz+mX5TUH7k=
dep github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
dep golang.org/x/tools v0.0.0-20190422233926-fe54fb35175b h1:NVD8gBK33xpdqCaZVVtd6OFJp+3dxkXuz7+U7KaVN6s=
build -buildmode=exe
build -compiler=gc
build DefaultGODEBUG=panicnil=1
build CGO_ENABLED=1
build CGO_CFLAGS=
build CGO_CPPFLAGS=
build CGO_CXXFLAGS=
build CGO_LDFLAGS=
build GOARCH=amd64
build GOOS=windows
build GOAMD64=v1go mismo es un archivo binario, de hecho sin ningún parámetro, go version muestra la versión del lenguaje go de su propio archivo binario, porque todo el toolchain de cmd/go está implementado en el lenguaje go mismo.
env
A través del comando env puedes ver la información de todas las variables de entorno de go, modificar estas variables de entorno afectará el comportamiento del toolchain de go.
$ go env -h
usage: go env [-json] [-u] [-w] [var ...]
Run 'go help env' for details.Sin ningún parámetro, mostrará los valores de todas las variables de entorno de go
$ go env
set GO111MODULE=on
set GOARCH=amd64
...Pasando el nombre de una variable de entorno como parámetro puedes mostrar solo el valor de esa variable
$ go env GO111MODULE
onAgregando -json puedes mostrar su formato json
$ go env -json
{
"AR": "ar",
"CC": "gcc",
......
}A través del flag -w, y usando la forma var=value como parámetro, modificarás permanentemente el valor de una variable
$ go env -w GO111MODULE=onUsando el flag -u, puedes restaurar una variable a su valor predeterminado
$ go env -u GO111MODULEEjecutando go help environment puedes ver la introducción de cada variable de entorno
$ go help environment
The go command and the tools it invokes consult environment variables
for configuration. If an environment variable is unset or empty, the go
command uses a sensible default setting. To see the effective setting of
the variable <NAME>, run 'go env <NAME>'. To change the default setting,
run 'go env -w <NAME>=<VALUE>'. Defaults changed using 'go env -w'
are recorded in a Go environment configuration file stored in the
per-user configuration directory, as reported by os.UserConfigDir.
The location of the configuration file can be changed by setting
the environment variable GOENV, and 'go env GOENV' prints the
effective location, but 'go env -w' cannot change the default location.
See 'go help env' for details.
General-purpose environment variables:
GO111MODULE
Controls whether the go command runs in module-aware mode or GOPATH mode.
May be "off", "on", or "auto".
See https://golang.org/ref/mod#mod-commands.
GCCGO
The gccgo command to run for 'go build -compiler=gccgo'.
GOARCH
The architecture, or processor, for which to compile code.
Examples are amd64, 386, arm, ppc64.
GOBIN
The directory where 'go install' will install a command.
GOCACHE
The directory where the go command will store cached
information for reuse in future builds.
......A continuación se presentan algunas variables de entorno comúnmente usadas
GOVERSION
El valor de esta variable de entorno depende de la versión del lenguaje go, y el número de versión proviene del archivo $GOROOT/VERSION, que registra el número de versión actual de go y el tiempo de compilación.
$ cat $GOROOT/VERSION
go1.21.3
time 2023-10-09T17:04:35ZEl valor de la variable runtime.Version es el mismo que el valor de GOVERSION, y esta variable de entorno no puede ser modificada.
GOENV
En el directorio $GOROOT habrá un archivo de configuración predeterminado llamado go.env
$ cat $GOROOT/go.env
# This file contains the initial defaults for go command configuration.
# Values set by 'go env -w' and written to the user's go/env file override these.
# The environment overrides everything else.
# Use the Go module mirror and checksum database by default.
# See https://proxy.golang.org for details.
GOPROXY=https://proxy.golang.org,direct
GOSUMDB=sum.golang.org
# Automatically download newer toolchains as directed by go.mod files.
# See https://go.dev/doc/toolchain for details.
GOTOOLCHAIN=autoSu formato es simplemente la forma key=value, los valores de variables de entorno modificados a través del comando go env -w key=value se escribirán en el archivo de configuración. Sin embargo, también puedes no usar el archivo de configuración predeterminado, la variable de entorno GOENV puede especificar manualmente la dirección del archivo de configuración env, y el valor de la variable de entorno GOENV solo puede ser sobrescrito por variables de entorno del sistema operativo, no puede ser modificado por el comando go env -w.
GOHOSTARCH
Representa la arquitectura de CPU de la máquina local, solo se usa para mostrar, el valor de esta variable de entorno no se lee del archivo de configuración, ni puede ser modificado.
GOHOSTOS
Representa el sistema operativo de la máquina local, solo se usa para mostrar, el valor de esta variable de entorno no se lee del archivo de configuración, ni puede ser modificado.
GOOS
Al compilar, el valor de GOOS determinará en qué sistema operativo se compilará el código fuente a archivo binario, el valor predeterminado es GOHOSTOS, es decir, el sistema operativo de la máquina local, tiene las siguientes opciones
linuxdarwinwindowsnetbsdaixandroid
Los sistemas operativos realmente soportados no son solo estos, usa el comando go tool dist list para ver todos los valores soportados
$ go tool dist list | awk -F '/' '{print $1}' | awk '!seen[$0]++'
aix
android
darwin
dragonfly
freebsd
illumos
ios
js
linux
netbsd
openbsd
plan9
solaris
wasip1
windowsGOARCH
Al compilar, el valor de GOARCH determinará qué instrucciones de arquitectura de CPU se usarán al compilar, el valor predeterminado es GOHOSTARCH, es decir, la arquitectura de CPU de la máquina local, tiene las siguientes opciones
amd64386armppc64
Las arquitecturas realmente soportadas no son solo estas, usa el comando go tool dist list para ver todos los valores soportados
$ go tool dist list | awk -F '/' '{print $2}' | awk '!seen[$0]++'
ppc64
386
amd64
arm
arm64
riscv64
wasm
loong64
mips
mips64
mips64le
mipsle
ppc64le
s390xTen en cuenta que GOOS y GOARCH no se pueden combinar arbitrariamente, algunos sistemas operativos solo soportan arquitecturas de CPU específicas.
GOROOT
GOROOT representa el directorio raíz de la instalación del lenguaje go, el valor de GOROOT no se puede modificar directamente, y solo puede ser sobrescrito por variables de entorno del sistema operativo.
$ ls $GOROOT -1
api
bin
codereview.cfg
CONTRIBUTING.md
doc
go.env
lib
LICENSE
misc
PATENTS
pkg
README.md
SECURITY.md
src
test
VERSIONEn el directorio raíz hay las siguientes carpetas o archivos más importantes
lib, almacena algunas dependencias, actualmente solo hay una biblioteca que contiene información de zonas horarias de países de todo el mundo, ubicada en$GOROOT/lib/time, los archivos binarios compilados no incluirán esta información de zonas horarias.pkg, almacena algunas bibliotecas de herramientas y archivos de cabecera, por ejemplo el comandogo toolbuscará los archivos binarios del toolchain de go en el directorio$GOROOT/pkg/toolbin, almacena archivos binarios, por defecto solo hay dos archivos ejecutablesgoygofmt,$GOROOT/bindebe ser agregado a las variables de sistema, de lo contrario no se podrán usar los comandos de go.src, almacena el código fuente de goVERSION, este archivo almacena la información de versión del lenguaje gogo.env, este archivo es el archivo de configuraciónenvpredeterminado
GOPATH
El valor predeterminado de GOPATH es $HOME/go, el valor de esta variable de entorno especifica dónde buscar los archivos importados al resolver declaraciones import. En los primeros tiempos sin gomod, GOPATH se usaba específicamente para almacenar varias bibliotecas de terceros, su estructura es la siguiente
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)Después del nacimiento de gomod, GOPATH es solo un lugar para almacenar las dependencias descargadas por go get, y para almacenar los archivos binarios descargados y compilados por go install. Ten en cuenta que la ubicación de GOPATH no puede ser la misma que GOROOT, de lo contrario no tendrá ningún efecto.
$ go env GOBIN
warning: GOPATH set to GOROOT (/home/user/go) has no effectHasta el momento en que escribo este artículo, la versión del lenguaje go ha llegado a go1.21.3, excepto por proyectos muy antiguos, básicamente nadie usa gopath para gestionar dependencias.
GOBIN
GOBIN se usa para almacenar los archivos binarios ejecutables de terceros descargados y compilados por go install, su valor predeterminado es $GOPATH/bin. Al igual que $GOROOT/bin, este directorio debe ser agregado a las variables de entorno del sistema operativo, de lo contrario tampoco se podrán usar los archivos binarios en el directorio GOBIN.
GOMODCACHE
GOMODCACHE indica la ubicación donde se almacenan las dependencias descargadas por go get, el valor predeterminado es $GOPATH/pkg/mod. Su formato de almacenamiento es el siguiente
$GOMODCACHE/domain/username/project@verionEn el mismo directorio de nivel también habrá una carpeta llamada sumdb, usada para almacenar información relacionada con la base de datos de suma de verificación de dependencias.
GOCACHE
Almacena información de caché para compilación, su valor predeterminado es $HOME/.cache/go-build, en este directorio se generará un archivo README.
$ cat $(go env GOCACHE)/README
This directory holds cached build artifacts from the Go build system.
Run "go clean -cache" if the directory is getting too large.
Run "go clean -fuzzcache" to delete the fuzz cache.
See golang.org to learn more about Go.Cada build producirá muchos archivos, go almacenará en caché estos archivos para reutilizarlos en la siguiente compilación.
GOTEMPDIR
Usado para archivos temporales generados durante la compilación, por ejemplo el archivo binario temporal que go run va a ejecutar. Su valor predeterminado es el directorio temporal especificado por el sistema operativo, en mac o linux es /tmp, en windows es %TEMP%, también se puede modificar a una ubicación especificada por el usuario.
GO111MODULE
Esta variable de entorno indica qué método usar para gestionar las dependencias del proyecto go, tiene los siguientes tres valores disponibles
off, desactivar gomod, usar gopath, e ignorar todos los archivosgo.modon, usar gomod, no usar gopath (predeterminado).auto, detección automática, si el archivo del proyecto contienego.modse usará gomod para gestionarlo
TIP
¿Por qué se llama GO111MODULE y no GOMODULE directamente? Porque gomod se introdujo por primera vez en la versión go1.11.
GOPROXY
Proxy de módulos go, el valor predeterminado es https://proxy.golang.org,direct, las url se separan por comas, direct significa usar directamente VCS saltando el proxy de módulos, solo se ejecutará el segundo cuando el primero no pueda acceder, otra opción disponible es off, que significa prohibir la descarga de cualquier módulo. Además, GOPROXY también puede ser una dirección de archivo, por ejemplo
GOPROXY=file://$(go env GOMODCACHE)/cache/downloadA través de go get -x puedes ver los comandos ejecutados durante el proceso de descarga de dependencias, para saber si se usó el proxy.
$ go get -x github.com/spf13/cast
# get https://goproxy.cn/github.com/@v/list
# get https://goproxy.cn/github.com/spf13/cast/@v/list
# get https://goproxy.cn/github.com/spf13/@v/list
# get https://goproxy.cn/github.com/spf13/@v/list: 404 Not Found (0.118s)
# get https://goproxy.cn/github.com/@v/list: 404 Not Found (0.197s)
# get https://goproxy.cn/github.com/spf13/cast/@v/list: 200 OK (0.257s)
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.info
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.info: 200 OK (0.013s)
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.mod
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.mod: 200 OK (0.015s)
# get https://goproxy.cn/sumdb/sum.golang.org/supported
# get https://goproxy.cn/sumdb/sum.golang.org/supported: 200 OK (0.064s)
# get https://goproxy.cn/sumdb/sum.golang.org/lookup/github.com/spf13/cast@v1.5.1
# get https://goproxy.cn/sumdb/sum.golang.org/lookup/github.com/spf13/cast@v1.5.1: 200 OK (0.014s)
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x079/736
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x079/736: 200 OK (0.016s)
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x068/334
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/1/266
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/0/x068/334: 200 OK (0.023s)
# get https://goproxy.cn/sumdb/sum.golang.org/tile/8/1/266: 200 OK (0.028s)
go: downloading github.com/spf13/cast v1.5.1
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.zip
# get https://goproxy.cn/github.com/spf13/cast/@v/v1.5.1.zip: 200 OK (0.024s)
go: added github.com/spf13/cast v1.5.1Usar un proxy de módulos puede mejorar efectivamente la velocidad de descarga de módulos, para usuarios en China continental básicamente no se puede acceder al proxy oficial predeterminado sin usar un proxy, actualmente los proxies de módulos de terceros públicos y confiables son los siguientes
https://proxy.golang.com.cn, código abierto y también proporciona servicios empresarialeshttps://goproxy.cn, proporcionado y con código abierto por Qiniu Cloud
Por supuesto, también hay soluciones de proxy de módulos auto-construidas de código abierto: goproxy
GOSUMDB
GOSUMDB se usa para configurar la dirección de la base de datos de verificación de suma de bibliotecas de dependencias, el valor predeterminado es sum.golang.org, cuando configuras un proxy, go accederá a la base de datos de verificación a través del proxy.
GOPRIVATE
La variable de entorno GOPRIVATE se usa para configurar bibliotecas privadas, las bibliotecas que coincidan no serán verificadas a través de sumdb, ni pasarán por el proxy, descargarán dependencias directamente a través de VCS. Soporta configuración con comodines, separados por comas, como se muestra a continuación, todas las dependencias con sufijo corp.example.com y llamadas github.com/gohper/myproject no pasarán por proxy ni sumdb.
GOPRIVATE=*.corp.example.com,github.com/gohper/myprojectTambién se puede configurar directamente para un usuario u organización
GOPRIVATE=github.com/gopher,github.com/myorganizationGONOPROXY
Indica qué dependencias no necesitan pasar por el proxy, las reglas son las mismas que GOPRIVATE, y sobrescribirá GOPRIVATE.
GONOSUMDB
Indica qué dependencias no necesitan pasar por la base de datos de verificación, las reglas son las mismas que GOPRIVATE, y sobrescribirá GOPRIVATE.
GOINSECURE
Indica qué dependencias se descargan directamente usando VCS, las reglas son las mismas que GOPRIVATE, y será sobrescrito por GONOPROXY y GONOSUMDB.
GOVCS
Configura el sistema de control de versiones para la gestión de módulos, por defecto public:git|hg,private:all. También se puede limitar el VCS para dominios específicos, por ejemplo
GOVCS=github.com:git,evil.com:off,*:git|hgEn la limitación anterior, github solo puede usar git, evil.com no permite usar ninguno, se usa | para indicar múltiples VCS. Si no quieres hacer ninguna limitación, puedes configurar
GOVCS=*:allSi no quieres permitir el uso de ningún VCS, puedes configurar
GOVCS=*:offGOWORK
Configura si se habilita el workspace, por defecto está vacío es decir habilitado, si se configura como off, no se habilitará, ignorará todos los archivos go.work.
GOTOOLDIR
Configura la ubicación del toolchain de go a usar, por defecto es $GOROOT/pkg/tool, el toolchain predeterminado también se almacena en esa ubicación.
GODEBUG
Configura opciones de depuración, en forma de pares clave-valor para controlar parte del comportamiento de ejecución de los programas go, por ejemplo
GODEBUG=http2client=0,http2server=0Estas configuraciones son para facilitar el retorno al comportamiento antiguo cuando aparecen cambios incompatibles durante el proceso de actualización de versión, por ejemplo en 1.21 ya no se permite la situación panic(nil), para esto, el oficial de go ha registrado específicamente GODEBUG History, visita GODEBUG para más detalles.
CGO_ENABLED
Indica si se habilita cgo, el valor predeterminado es 1, es decir habilitado, configurar como 0 lo deshabilita.
Las variables de entorno anteriores son todas comúnmente usadas, para algunas no tan comúnmente usadas no se hará demasiada introducción, como CGO, WASM, etc., si te interesa puedes investigar por tu cuenta.
build
Go soporta dos tipos de compiladores, gccgo y gc. gcc es un compilador de c/c++ con historia, soporta múltiples lenguajes incluyendo go, este último gc no se refiere a garbage collection, se refiere a go compiler, el lenguaje go completó el bootstrap en go1.5, gc es un compilador completamente escrito en el lenguaje go, su código fuente está ubicado en el paquete cmd/compile, como está completamente implementado en go, es muy conveniente para entender y aprender sus mecanismos internos. Por defecto, el compilador usa gc para compilar. Por cierto, el depurador del lenguaje go también tiene dos tipos, gdb y dlv, el primero es el depurador de c/c++ con historia, soporta múltiples lenguajes incluyendo go, el segundo es un depurador escrito en go, tiene mejor soporte para el lenguaje go, también es de código abierto, se recomienda usar el segundo.
El comando build compila archivos fuente de go en archivos binarios ejecutables, experimentarás una compilación bastante rápida, esta es también una de las características del lenguaje go.
$ go build -h
usage: go build [-o output] [build flags] [packages]
Run 'go help build' for details.Acepta tres parámetros, uno es la ruta de salida de archivo indicada por el flag -o, otro son los flags de compilación build flags usados para definir el comportamiento de compilación, y el último es el paquete a compilar, este parámetro debe ir al final. Aquí hay un ejemplo simple, sin usar flags de compilación.
# Windows
$ go build -o .\bin\golearn.exe golearn
# macOS / Linux
$ go build -o ./bin/golearn golearn./bin/golearn.exe indica la ruta de salida, golearn indica el módulo a compilar, también puede ser un archivo de entrada, o una carpeta. Por ejemplo, el siguiente ejemplo simple usa el archivo de entrada main.go como objetivo de compilación.
# Windows
$ go build -o .\bin\golearn.exe main.go
# macOS / Linux
$ go build -o ./bin/golearn main.goAl compilar ignorará todos los archivos que terminen en _test.go, porque estos archivos por convención son todos archivos de prueba.
Además, el comando build también soporta bastantes flags de compilación para controlar algunos comportamientos durante la compilación.
-x:muestra las instrucciones detalladas durante el proceso de compilación-n:similar a-x, pero la diferencia es que solo muestra estas instrucciones, pero en realidad no las ejecuta.-v:muestra los paquetes compilados-p:número de concurrentes durante el proceso de compilación-a:fuerza la recompilación, incluso si ya está actualizado.-compiler:especifica qué compilador usar,gccgoogc, este último es un compilador escrito en go.-race:habilita la detección de race condition-msan:habilita el análisis de memoria-asan:habilita el análisis de direcciones-cover:habilita la detección de cobertura de código-buildmode:especifica el modo de compilación, tiene las opcionesarchive,c-archive,c-shared,default,shared,exe,pie,plugin.-pgo, especifica el archivo pgo-trimpath:elimina el prefijo de ruta de archivos fuente, por ejemplo la ruta relativa/var/lib/go/src/main.go, después de eliminar, el nombre de archivo obtenido a través deruntimeen tiempo de ejecución solo tendrá la ruta relativa relativa a la ruta del módulo/main.go, después de habilitar esto, el tiempo de compilación aumentará significativamente, aproximadamente un 20-40%, dependiendo del número de archivos.-toolexec, algunos comandos go ejecutados antes de compilar, el formato es-toolexec 'cmd args'.-gcflags:especifica algunos tag del compilador gc-gccgoflags:especifica algunos tag del compilador gccgo-ldflags:especifica algunos tag de la herramienta link
Para algunos parámetros pasados como ldflags, puedes pasar "-help" para obtener sus posibles valores, por ejemplo
$ 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
......Los anteriores son comúnmente usados, para otros no tan comúnmente usados puedes investigar por tu cuenta.
gcflags
A través de gcflags puedes pasar algunos parámetros al compilador gc para controlar comportamientos específicos, su formato de uso es -gcflags="pattern=args list", ages list es la lista de parámetros, pattern es el alcance, tiene los siguientes valores disponibles
main, la ruta del paquete de nivel superior donde se encuentra el archivo de entradaall, el módulo actual y todas las dependencias del modo actualstd, biblioteca estándarcmd, afecta todos los archivos fuente bajo el paquetecmd- Comodines, como
.,./...,cmd/....
Esta regla de pattern aplica a todos los flags que soportan este formato, por ejemplo ldflags. A través del siguiente comando puedes ver los valores disponibles de sus parámetros
$ go build -gcflags -help
用法:compile [选项] file.go...
-% 调试非静态初始化器
-+ 编译运行时
-B 禁用边界检查
-C 禁用错误消息中的列号打印
-D path
设置本地导入的相对路径
-E 调试符号导出
-I directory
添加目录到导入搜索路径
-K 调试缺失的行号
-L 对于受 //line 指令影响的错误位置,同时显示实际源文件名
-N 禁用优化
-S 打印汇编列表
-V 打印版本并退出
-W 类型检查后调试解析树
......A continuación se presentan algunos parámetros comúnmente usados
-S:muestra el código en forma de ensamblador-N:desactiva las optimizaciones del compilador-m:muestra las decisiones de optimización-l:desactiva el inline de funciones-c:número de concurrentes en la compilación-dwarf:genera banderas DWARF
Por ejemplo, si quieres ver la forma de ensamblador del código, puedes usar el parámetro -S, y también debes desactivar las optimizaciones y el inline, para poder restaurar su forma original, de la siguiente manera
$ 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
A través de ldflags puedes pasar algunos parámetros al linker para controlar comportamientos específicos, a través del siguiente comando puedes ver todos los valores disponibles de ldflags, cerca de veinte o treinta.
$ 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)
.....El parámetro -X de ldflags es una función muy práctica, puede definir el valor de una variable de cadena de un paquete especificado en tiempo de enlace. A través de esta función, podemos inyectar información meta muy convenientemente en tiempo de compilación. Y como es solo una variable, también es conveniente obtenerla en tiempo de ejecución, aquí hay un ejemplo simple.
package main
import "fmt"
var (
Version string
)
func main() {
fmt.Println(Version)
}Ejecuta el comando
go build -ldflags "-X main.Version=$(git describe --always)" main.goDespués de ejecutar, mostrará el checksum sha1 del commit de git.
5e3fd7aOtros parámetros prácticos incluyen
-w:no generar DWARF, esto es información para facilitar la depuración del código fuente.-s:desactivar la tabla de símbolos
Estos dos generalmente se usan juntos, pueden reducir significativamente el tamaño del archivo binario compilado, aproximadamente un 40%-50%, la desventaja también es obvia, no se puede depurar, aquí hay un ejemplo.
$ go build -ldflags="-w -s" main.goCompilación Cruzada
La compilación del lenguaje go tiene dos características principales, la primera es rápida, la otra característica principal es la compilación cruzada, la compilación cruzada se refiere a poder compilar localmente en código objeto de otros sistemas, por ejemplo compilar en windows archivos binarios para linux o darwin, y viceversa. La compilación cruzada soporta muchos lenguajes, esto no es nada raro, pero la compilación cruzada del lenguaje go es muy simple, solo requiere los siguientes dos pasos
- Configurar la variable de entorno GOOS, elegir tu sistema operativo objetivo
- Configurar la variable de entorno GOARCH, elegir la arquitectura de CPU objetivo
- Usar
go buildpara compilar como de costumbre
Todo el proceso es muy corto, no requiere usar herramientas adicionales o configuración, y la velocidad es tan rápida como de costumbre. Como se muestra a continuación
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_winEl primer paso SET CGO_ENABLED=0 desactiva cgo, una vez que tu código usa cgo, no podrás usar la compilación cruzada normalmente. El segundo paso SET GOOS configura el sistema objetivo, las opciones disponibles son linux, darwin, windwos, netbsd. El tercer paso configura la arquitectura de CPU, SET GOARCH, las opciones disponibles son amd64, 386, arm, ppc64. El último paso es compilar como de costumbre.
Control de Compilación
El comando build puede lograr el efecto de controlar la compilación a través de tags, existe en el código fuente en forma de directivas, veamos un ejemplo, archivo product.go
// +build product
package main
import "fmt"
func main() {
fmt.Println("product")
}Archivo debug.go
// +build debug
package main
import "fmt"
func main() {
fmt.Println("debug")
}Ambos tienen una directiva // +build, que indica en qué condiciones serán compilados. Su formato básico es
// +build tag1 tag2
package pkg_nameHay algunas reglas que se deben cumplir
- Debe haber un espacio entre
//y+build - Debe estar ubicado encima de la declaración del paquete
- Debe haber una línea vacía entre la declaración del paquete
Además, también puede lograr control lógico a través de separación simple, el espacio indica OR, la coma indica AND, ! indica NOT. Por ejemplo, el siguiente ejemplo
// +build windows linux
package pkg_nameIndica que en la plataforma windows o linux se compilará el archivo actual.
// +build windows,amd64,!cgo linux,i386,cgo
package pkg_nameEste ejemplo indica que en la plataforma windows con arquitectura amd64 y cgo no habilitado, o en la plataforma linux con arquitectura i386 y cgo habilitado se compilará. Si solo no quieres que un archivo participe en la compilación, puedes usar ignore.
// +build ignore
package pkg_nameTambién puede haber múltiples líneas de directivas
// +build windows
// +build amd64
package pkg_nameLas directivas de múltiples líneas se procesan en modo AND. Para los tags de plataforma y arquitectura, go los pasará automáticamente al compilar, también podemos pasar tags personalizados, tomando los dos archivos del ejemplo anterior
$ go build -tags="debug" . && ./golearn.exe
debug
$ go build -tags="product" . && ./golearn.exe
productSe puede ver que al pasar diferentes tags la salida es diferente, el propósito del control de compilación se ha logrado.
run
El comando run al igual que build compilará el código fuente, la diferencia es que el comando run lo ejecutará directamente después de completar la compilación. El comando run para acelerar la compilación, no genera información de depuración durante el proceso de compilación, por lo que no soporta depuración, y solo genera un archivo binario temporal, generalmente almacenado en el directorio GOTMEPDIR, por ejemplo /temp/go-build2822241271/b001/exe/main.exe.
$ go run -h
usage: go run [build flags] [-exec xprog] package [arguments...]
Run 'go help run' for details.También soporta los flags de compilación del comando build, y también proporciona un parámetro -exec para indicar qué programa ejecutará el archivo binario, [arguments...] se refiere a los parámetros de ejecución del programa. Aquí hay un ejemplo
package main
import (
"fmt"
"os"
)
var (
Version string
)
func main() {
fmt.Println(Version)
fmt.Println(os.Args[1:])
}Usa go run para ejecutar
$ go run -ldflags="-X main.Version=$(git describe --always)" main.go hello
5e3fd7a
[hello]En general, el uso no es muy diferente de go build, por lo que no se hará más explicación.
tool
El comando tool en sí mismo no tiene ninguna función, su función es llamar directamente a las herramientas en el directorio cmd/, por ejemplo cmd/compile es el compilador incluido. A través de go tool puedes llamar directamente a estas herramientas, sin tener que ejecutar manualmente los archivos binarios de estas herramientas.
$ go tool -h
usage: go tool [-n] command [args...]Usa el parámetro -n para imprimir todos los parámetros de comando que soporta
$ go tool -n
addr2line
asm
buildid
cgo
compile
covdata
cover
doc
fix
link
nm
objdump
pack
pprof
test2json
trace
vetEstas herramientas se almacenan en el directorio GOROOT/pkg/tool, y se agrupan según el sistema operativo y la arquitectura de CPU, de la siguiente manera.
$ 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*Usa el formato go doc cmd/command para ver el uso de cada comando, por ejemplo
$ 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.
...Los flags soportados por cmd/compile son los mismos que los soportados por gcflags mencionados anteriormente. La diferencia entre go tool compile y go build es que el primero solo es responsable de compilar, y solo puede tomar archivos como parámetros, el segundo puede tomar carpetas, paquetes, archivos como parámetros, y no solo compila el código fuente, también es responsable de enlazar archivos, limpiar archivos inútiles, etc., el primero es parte del segundo. Podemos imprimir los comandos ejecutados durante el proceso de build
$ go build -n main.go
#
# internal/goarch
#
mkdir -p $WORK\b004\
cat >$WORK\b004\importcfg << 'EOF' # internal
# import config
EOF
"/golang/pkg/tool/windows_amd64/compile.exe" -o "$WORK/b004/_pkg_.a" -trimpath "$WORK/b004=>" -p internal/goarch -std -+ -complete -buildid 3gunEkUExGdhOPa2rFsh/3gunEkUExGdhOPa2rFsh -goversion go1.21.0 -c=4 -nolocalimports -importcfg "$WORK/b004/importcfg" -pack "/golang/src/internal/goarch/goarch.go" "/golang/src/internal/goarch/goarch_amd64.go" "/golang/src/internal/goarch/zgoarch_amd64.go"
"/golang/pkg/tool/windows_amd64/buildid.exe" -w "$WORK/b004/_pkg_.a" # internal
...Durante el proceso puedes ver este segmento /golang/pkg/tool/windows_amd64/compile.exe, que está llamando al compilador. Además de compile, hay muchas herramientas que se pueden llamar, muchos comandos go en realidad son alias de ellas.
clean
El comando clean se usa para eliminar los archivos objeto generados durante el proceso de compilación
$ go clean -h
usage: go clean [clean flags] [build flags] [packages]
Run 'go help clean' for details.Soporta los siguientes flags
-i:elimina los archivos de almacenamiento o archivos binarios correspondientes-n:imprime los comandos que se ejecutarán durante el proceso de limpieza pero en realidad no los ejecuta-x:imprime los comandos que se ejecutarán durante el proceso de limpieza y los ejecuta-r:elimina recursivamente a través deimport path-cache, elimina toda la caché generada porgo build-testcache:elimina toda la caché de pruebas generada-modcache:elimina toda la caché de módulos descargados-fuzzcache:elimina la caché generada porfuzz test.
Cuando usas go tool compile, estás llamando directamente al comando del compilador, no como go build que hace mucho procesamiento posterior, se generarán archivos objeto. Por ejemplo, ejecuta el siguiente comando
go tool compile -N -S -l main.goSe generará un archivo llamado main.o, usa el comando go clean para eliminarlo. O usa el parámetro -n para imprimir los comandos que se ejecutarán.
$ 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.exeLimpia la caché de compilación, eliminará la caché de compilación generada en el directorio GOCACHE
$ go clean -cache -n
rm -r /cache/00 /cache/01 /cache/02Limpia la caché generada por fuzz test, esta caché por defecto se almacena en el directorio GOCACHE/fuzz/
$ go clean -fuzzcache -n
rm -rf /cache/fuzzfix
El lenguaje go hasta el momento de escribir este artículo ya tiene diez años, en el proceso de actualización y modificación continua del lenguaje, inevitablemente aparecerán algunos problemas de incompatibilidad debido a cambios en la API, el comando fix nació para esto, detectará esas API obsoletas en los archivos fuente y las reemplazará con nuevas API.
$ go fix -h
usage: go fix [-fix list] [packages]
Run 'go help fix' for details.Soporta carpetas, nombres de archivo, directorios como parámetros, acepta el flag -fix para pasar parámetros que indican qué modificaciones hacer, puedes ver los valores disponibles a través del comando got tool fix -help
$ go tool fix -help
usage: go tool fix [-diff] [-r fixname,...] [-force fixname,...] [path ...]
-diff
display diffs instead of rewriting files
-force string
force these fixes to run even if the code looks updated
-go string
go language version for files
-r string
restrict the rewrites to this comma-separated list
Available rewrites are:
buildtag
Remove +build comments from modules using Go 1.18 or later
cftype
Fixes initializers and casts of C.*Ref and JNI types
context
Change imports of golang.org/x/net/context to context
egl
Fixes initializers of EGLDisplay
eglconf
Fixes initializers of EGLConfig
gotypes
Change imports of golang.org/x/tools/go/{exact,types} to go/{constant,types}
jni
Fixes initializers of JNI's jobject and subtypes
netipv6zone
Adapt element key to IPAddr, UDPAddr or TCPAddr composite literals.
https://codereview.appspot.com/6849045/
printerconfig
Add element keys to Config composite literals.Veamos un ejemplo, el código fuente usa el paquete golang.org/x/net/context
package main
import (
"fmt"
"golang.org/x/net/context"
)
func main() {
background := context.Background()
fmt.Println(background.Err())
}Usa go fix para corregirlo, reemplazándolo con el paquete context de la biblioteca estándar, podemos usar el siguiente comando para hacer el reemplazo
$ go fix -fix context main.goTambién puedes ver los cambios antes y después sin reemplazar.
$ 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() {El lenguaje go ha existido por más de diez años y solo tiene nueve parámetros de reemplazo disponibles, se puede ver que la compatibilidad se ha mantenido bastante bien.
fmt
El comando fmt es una herramienta de formateo incluida en el lenguaje go, usada para formatear archivos de código fuente go.
$ go fmt -h
usage: go fmt [-n] [-x] [packages]
Run 'go help fmt' for details.A través del comando go doc gofmt puedes ver su documentación detallada
$ go doc cmd/gofmt
Gofmt formats Go programs. It uses tabs for indentation and blanks for
alignment. Alignment assumes that an editor is using a fixed-width font.
Usage:
gofmt [flags] [path ...]
The flags are:
-d
Do not print reformatted sources to standard output.
If a file's formatting is different than gofmt's, print diffs
to standard output.
-e
Print all (including spurious) errors.
-l
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, print its name
to standard output.
-r rule
Apply the rewrite rule to the source before reformatting.
-s
Try to simplify code (after applying the rewrite rule, if any).
-w
Do not print reformatted sources to standard output.
If a file's formatting is different from gofmt's, overwrite it
with gofmt's version. If an error occurred during overwriting,
the original file is restored from an automatic backup.gofmt usa tab para la indentación, espacios para la alineación, por defecto el código formateado se mostrará en la salida estándar, no sobrescribe el archivo original. El comando go fmt en realidad usa el comando gofmt, es un archivo binario independiente, ubicado en el directorio GOROOT/bin.
$ ls $GOROOT/bin -1
go.exe*
gofmt.exe*Agregando el flag -n al comando go fmt puedes saber qué instrucciones se ejecutarán.
$ go fmt main.go
/golang/bin/gofmt.exe -l -w main.goSe puede ver que go fmt es en realidad un alias de gofmt -l -w, el comando gofmt tiene los siguientes parámetros
-d:muestra la diferencia del archivo antes y después del formateo-e:muestra todos los errores-l:muestra los nombres de archivos que han cambiado-r:aplica reglas de formateo-s:intenta simplificar el código-w:sobrescribe el archivo fuente, si ocurre un error restaura la copia de seguridad
Supongamos que ahora tenemos el siguiente archivo fuente
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")}A través del parámetro -d puedes previsualizar sus cambios
$ 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!")
+}El parámetro -l mostrará los nombres de archivos que se modificarán
$ gofmt -l .
main.goSi hay errores de sintaxis, el parámetro -e puede mostrar más detalles
$ gofmt -d -e main.go
main.go:6:27: missing ',' in argument list
main.go:6:28: expected operand, found newline
main.go:7:2: expected ')', found 'EOF'
main.go:7:2: expected ';', found 'EOF'
main.go:7:2: expected ';', found 'EOF'
main.go:7:2: expected '}', found 'EOF'
main.go:7:2: missing ',' in argument list-w aplicará los cambios al archivo fuente
$ gofmt -l -w .
main.go
$ cat main.go
package main
import "fmt"
func main() {
fmt.Println("hello world!")
}Puedes notar que como herramienta de formateo, gofmt no proporciona ninguna configuración personalizada, mientras que el formateador prettify diseñado para embellecer código js proporciona bastantes configuraciones para formatear código, aquí se puede reflejar una actitud del oficial de go, no pienses en hacer personalización, es mejor que el estilo de código de todos sea consistente, al menos hay un beneficio, al leer código no tienes que adaptarte a los hábitos de otros. Sin embargo, en realidad todavía conserva una opción de personalización, que es la regla de reemplazo del código formateado, la regla se puede personalizar, el formato es el siguiente
pattern -> replacementPor ejemplo, eliminar paréntesis redundantes
(a) -> aVer los cambios del archivo
$ 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!")
}Se puede ver que gofmt eliminará los paréntesis redundantes.
get
El comando get es definitivamente uno de los más usados en el desarrollo de go, su función es descargar el código fuente de la dirección especificada al directorio correspondiente a GOMODCACHE.
$ go get -h
usage: go get [-t] [-u] [-v] [build flags] [packages]
Run 'go help get' for details.-u:intenta actualizar la versión menor y la versión de parche del paquete, si hay un cambio en la versión principal, comov1->v2, no se actualizará.-t:actualiza la versión de dependencias en las pruebas-v:muestra los paquetes compilados, en realidad es uno de los parámetros debuild flags
En tiempos antiguos, go get funcionaba de manera similar a go install, descargaba y compilaba estos paquetes, sin embargo con el nacimiento y perfeccionamiento de los módulos de go, esta parte de la función gradualmente quedó obsoleta, el comando get ahora se usa más comúnmente para descargar y resolver dependencias de módulos go, por lo que puedes ver que el comando go get también soporta flags de compilación como build flags, y si intentas usar go get fuera de un módulo como usarías go install, te indicará que este uso ha sido obsoleto.
$ 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'.En cuanto a por qué en la descripción de la documentación todavía se conservan estos, es desconocido, revisando el código fuente del comando get, también descubrirás que conserva esos flags antiguos.
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
)Volviendo al tema, el comando get descargará el código fuente del paquete especificado al directorio de dependencias global local, es decir, el directorio correspondiente a GOCACHE, y luego registrará la información en los archivos go.mod y go.sum, el primero es responsable de registrar versiones, el segundo es responsable de registrar checksums sha1 para garantizar la seguridad. El comando get en realidad se basa en VCS, es decir, el sistema de control de versiones local, soporta los siguientes
- git
- hg (Mercurial)
- bzr (Bazaar)
- svn
- fossil
Entre ellos, por defecto solo soporta git y hg, se puede configurar en GOVCS, el formato es el siguiente
GOVCS=github.com:git,example.com:hg,*:git|hg,*:allGOVCS solo soporta git y hg como VCS, los otros tres necesitan configurarse en GOPRIVATE.
El comando go get tiene los siguientes usos, puedes pasar la dirección de dependencia directamente como parámetro
$ go get golang.org/x/netTambién puedes especificar la versión
$ go get golang.org/x/net@0.17.0Especificar la última versión
$ go get golang.org/x/net@latestIntentar actualizar la versión
$ go get -u golang.org/x/netEliminar una dependencia
$ go get golang.org/x/net@noneLos usos anteriores son para gestionar dependencias normales, también se puede usar para gestionar dependencias menos normales, por ejemplo actualizar la versión del lenguaje go
$ go get go@latest
go: updating go.mod requires go >= 1.21.3; switching to go1.21.3
go: downloading go1.21.3 (windows/amd64)
go: upgraded go 1.21.0 => 1.21.3Incluso se puede usar para actualizar la versión del toolchain de go
$ go get toolchain@latestCuando usas go get para actualizar las versiones de go y toolchain, se instalará la nueva versión de go en el directorio GOMODCACHE/golang.org/
$ ls $(go env GOMODCACHE)/golang.org -1
'toolchain@v0.0.1-go1.21.3.windows-amd64'/
x/Entonces puedes modificar manualmente GOROOT para cambiar a la versión especificada.
install
El comando install es similar al comando get, ambos se usan para descargar dependencias de terceros, pero la diferencia es que el comando get descarga el código fuente, mientras que el comando install compila el código fuente en archivos binarios ejecutables nativos, la ruta de almacenamiento de los archivos binarios es primero en el directorio GOBIN, y luego en GOPATH/bin. La función principal de este comando es descargar algunas herramientas de línea de comandos de terceros públicas, gracias a la velocidad de compilación y portabilidad del lenguaje go, no es necesario descargar archivos binarios, sino descargar directamente el código fuente y luego compilarlo localmente.
$ go install -h
usage: go install [build flags] [packages]
Run 'go help install' for details.El comando install acepta flags de compilación y nombres de paquetes como parámetros, con gomod habilitado, el nombre del paquete debe llevar el número de versión. Por ejemplo, descargar el depurador delve
$ go install -x github.com/go-delve/delve/cmd/dlv@latest
# get https://goproxy.cn/github.com/@v/list
# get https://goproxy.cn/github.com/go-delve/delve/cmd/@v/list
# get https://goproxy.cn/github.com/go-delve/delve/cmd/dlv/@v/list
# get https://goproxy.cn/github.com/go-delve/delve/@v/list
# get https://goproxy.cn/github.com/go-delve/@v/list
# get https://goproxy.cn/github.com/@v/list: 404 Not Found (0.014s)
# get https://goproxy.cn/github.com/go-delve/delve/cmd/@v/list: 404 Not Found (0.027s)
# get https://goproxy.cn/github.com/go-delve/delve/cmd/dlv/@v/list: 404 Not Found (0.027s)
# get https://goproxy.cn/github.com/go-delve/delve/@v/list: 200 OK (0.027s)
# get https://goproxy.cn/github.com/go-delve/@v/list: 404 Not Found (0.027s)
WORK=/home/user/tmp/go-build2033992495
mkdir -p $WORK/b001/
cat >/home/user/tmp/go-build2033992495/b001/importcfg.link << 'EOF' # internal
packagefile github.com/go-delve/delve/cmd/dlv=/home/user/.cache/go-build/f1/f11d552287458c0fce625abe50bf928c487064c36bbb1251ad8b1968772c3e4b-d
......
......
mkdir -p /home/wyh/gomod/bin/
mv $WORK/b001/exe/a.out /home/wyh/gomod/bin/dlv
rm -r $WORK/b001/Primero descarga el código fuente a la ruta almacenada en GOMODCACHE, esto es consistente con el comando get, luego cambia al directorio de trabajo temporal, lo compila, después de completar la compilación mueve el archivo binario al directorio GOPATH/bin, y finalmente elimina la carpeta temporal. El comando install también tiene una limitación, el paquete descargado debe ser el paquete de entrada del proyecto, es decir, debe contener el archivo de entrada main.go, de lo contrario te indicará que no se puede instalar. Por ejemplo, usar go install para descargar gin
$ go install -x github.com/gin-gonic/gin@latest
# get https://goproxy.cn/github.com/@v/list
# get https://goproxy.cn/github.com/gin-gonic/gin/@v/list
# get https://goproxy.cn/github.com/gin-gonic/@v/list
# get https://goproxy.cn/github.com/@v/list: 404 Not Found (0.022s)
# get https://goproxy.cn/github.com/gin-gonic/gin/@v/list: 200 OK (0.027s)
# get https://goproxy.cn/github.com/gin-gonic/@v/list: 404 Not Found (0.028s)
package github.com/gin-gonic/gin is not a main packagegin es una biblioteca de dependencias de framework web, no una herramienta de línea de comandos, naturalmente no tiene archivo de entrada, por lo que la instalación fallará.
list
El comando list listará los paquetes en la ubicación especificada, uno por línea, y soporta formato de salida personalizado, soporta muchos parámetros, el requisito previo para usarlo es estar en un proyecto que soporte gomod.
$ go list -h
usage: go list [-f format] [-json] [-m] [list flags] [build flags] [packages]
Run 'go help list' for details.Soporta los siguientes parámetros
-f:parámetro de formato-json:salida en formato json-compiled:muestra todos los paquetes que serán compilados por el compilador-deps:muestra cada paquete y el nombre de cada paquete del que depende-test:muestra el paquete de pruebas de cada paquete-e:salida normal cuando se encuentran paquetes con errores-find:no resuelve las dependencias de estos paquetes-export:cuando se usa este parámetro, se establece el campoPackage.Exportde la estructura para que contenga el archivo con la información de exportación más reciente del paquete especificado, y se establece el campoPackage.BuildIDcon elBuildIDdel paquete, principalmente para salida formateada.
Parámetros de información de módulos,
-m:muestra módulos en lugar de paquetes-versions:muestra toda la información disponible de un módulo-retracted:muestra las versiones retiradas de un módulo
El parámetro [packages] puede ser un nombre de paquete especificado, o una carpeta, o all, que significa cualquier lugar, cuando se usa el parámetro -m, all significa todas las dependencias referenciadas por el módulo actual.
Por ejemplo, el archivo actual solo tiene un archivo main.go, y solo hay una línea de código que muestra "hello world", después de ejecutar go list -deps ., mostrará todos los paquetes desde el proyecto actual hasta fmt y todas sus dependencias referenciadas.
$ 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
golearnO mostrar todas las dependencias de módulos en el proyecto actual
$ 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 salida del comando list es por línea, cada línea de salida es un paquete. El oficial proporciona un parámetro -f que nos permite personalizar el formato de salida de línea, el valor que acepta es la sintaxis de plantilla definida por el paquete de motor de plantillas template/text, por ejemplo el siguiente ejemplo
-f "package {{ .Dir }} {{ .Name }}"Cada paquete iterado se pasará en forma de la siguiente estructura, todos los campos de esta estructura se pueden usar como parámetros de plantilla.
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 se itera un módulo, se pasa en forma de la siguiente estructura, todos sus campos también se pueden usar como parámetros de plantilla.
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
}Ver todos los paquetes
$ 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 toolVer módulos
$ go list -m -f "mod {{.Path}} {{.Version}} {{.GoVersion}} {{.GoMod}}"
mod golearn 1.21.3 /golearn/go.modmod
go mod es un comando dedicado a gestionar módulos go.
$ go mod help
Go mod provides access to operations on modules.
Note that support for modules is built into all the go commands,
not just 'go mod'. For example, day-to-day adding, removing, upgrading,
and downgrading of dependencies should be done using 'go get'.
See 'go help modules' for an overview of module functionality.
Usage:
go mod <command> [arguments]
The commands are:
download download modules to local cache
edit edit go.mod from tools or scripts
graph print module requirement graph
init initialize new module in current directory
tidy add missing and remove unused modules
vendor make vendored copy of dependencies
verify verify dependencies have expected content
why explain why packages or modules are needed
Use "go help mod <command>" for more information about a command.Tiene los siguientes subcomandos
download:descarga todas las dependencias indicadas en el archivogo.moda la caché localedit:edita el archivogo.mod, la interfaz de línea de comandos que proporciona es principalmente para que otras herramientas o scripts la llamen.init:inicializa un proyecto gomod en el directorio actualtidy:descarga dependencias faltantes, elimina dependencias no usadasgraph:muestra el grafo de dependenciasverify:verifica las dependencias localeswhy:explica por qué se dependen de estos módulosvendor:exporta las dependencias del proyecto al directorio vendor
init
$ go help mod init
usage: go mod init [module-path]El comando init se usa para inicializar un proyecto gomod, su único parámetro es la ruta del módulo, si otros quieren descargar tu dependencia en el futuro, necesitarán usar esta ruta del módulo como referencia. Su regla de nomenclatura generalmente es
domain_name/user_name/repo_namePor ejemplo, generalmente todos ponen sus proyectos en github, así que puede ser
github.com/jack/gotourNo se recomienda usar símbolos especiales como ruta del módulo. Veamos un ejemplo de uso
$ mkdir gotour
$ cd gotour
$ go mod init "github.com/jack/gotour"
go: creating new go.mod: module github.com/jack/gotourtidy
$ go help mod tidy
usage: go mod tidy [-e] [-v] [-x] [-go=version] [-compat=version]El comando tidy limpiará las dependencias no usadas en go.mod, es decir, dependencias que no están referenciadas, y descargará aquellas dependencias que están referenciadas pero no existen. Soporta los siguientes parámetros
-v, muestra los módulos de dependencia que se eliminan-e, si ocurre un error durante el proceso, lo ignora y continúa ejecutando-x, muestra el proceso de ejecución-go=version, actualiza la versión de go en el archivogo.mod-compact=version, retiene cualquier checksum adicional necesario para cargar correctamente el grafo de módulos desde la versión principal de Go especificada, y si el comandogode esa versión carga cualquier paquete importado desde diferentes versiones de módulos, causará un error en tidy. Este parámetro raramente se usa, generalmente solo causa errores durante cambios de versión, puedes ver esta respuesta en stackoverflow go modules - go mod tidy error message: "but go 1.16 would select" - Stack Overflow
Veamos un ejemplo de uso
$ go mod tidy -v
unused github.com/246859/containers
unused github.com/246859/river
unused github.com/Jleagle/steam-go
unused github.com/Jleagle/unmarshal-go
unused github.com/KyleBanks/depth
unused github.com/Microsoft/go-winio
unused github.com/PuerkitoBio/purell
unused github.com/PuerkitoBio/urlesc
unused github.com/andeya/ameda
unused github.com/andeya/goutil
unused github.com/asaskevich/govalidator
unused github.com/buger/jsonparser
unused github.com/bwmarrin/snowflake
unused github.com/bytedance/go-tagexpr/v2
unused github.com/bytedance/sonic
unused github.com/cespare/xxhash/v2
unused github.com/chenzhuoyu/base64x
......download
$ go help mod download
usage: go mod download [-x] [-json] [-reuse=old.json] [modules]Aunque el nombre del comando download se traduce como descargar, solo descarga las dependencias a la caché de dependencias local, no modifica el archivo go.mod, su función es pre-descargar dependencias a la caché de archivos local, si quieres descargar una dependencia determinada, se recomienda usar go get o go mod tidy.
Aquí hay algunos ejemplos de uso
$ go mod download -x gorm.io/gorm
# get https://goproxy.cn/gorm.io/gorm/@v/list
# get https://goproxy.cn/gorm.io/gorm/@v/list: 200 OK (0.084s)Sin ningún parámetro, descargará todas las dependencias que existen en el archivo go.mod pero no existen en la caché de dependencias local, si no hay nada que descargar mostrará
go: no module dependencies to downloadedit
$ go help mod edit
usage: go mod edit [editing flags] [-fmt|-print|-json] [go.mod]edit es una interfaz de línea de comandos para modificar el archivo go.mod, generalmente se proporciona para que otros programas la usen, algunos editores IDE proporcionan soporte para gomod usando estos comandos. Soporta los siguientes parámetros
-module, modifica la ruta del módulo-go=version, modifica la versión de go esperada-require=path@version, añade una dependencia-droprequire=path@version, elimina una dependencia-exclude=path@version, añade una dependencia de exclusión-dropexclude=path@version, elimina una dependencia de exclusión-replace=old@version=new@version, añade una dependencia de reemplazo-dropreplace=old@version, elimina una dependencia de reemplazo-retract=version, añade un item de reversión de versión-dropretract=version, elimina un item de reversión de versión
También hay otros parámetros para mostrar
-print, muestra el contenido del archivo-json, muestra en formato json
Por ejemplo, el siguiente ejemplo
$ go mod edit -print
module golearn
go 1.21.3
require (
github.com/dstgo/task v1.2.0
github.com/spf13/cast v1.5.1
github.com/swaggo/swag v1.16.2
golang.org/x/net v0.19.0
gorm.io/gorm v1.25.5
)graph
$ go help mod graph
usage: go mod graph [-go=version] [-x]El comando graph mostrará el grafo de dependencias del proyecto actual, su legibilidad es muy pobre, y la mayoría de las veces no es para que lo lean los humanos, su resultado generalmente se procesa y luego se muestra de forma visualizada. Cada línea es una dependencia, su formato es el siguiente
referenciador referenciadoPor ejemplo
golearn go@1.21.3También soporta dos parámetros
-go=version, usa la versión de go dada para cargar el grafo de dependencias, su valor no puede ser menor que la versión en el archivogo.mod.-x, muestra los comandos ejecutados durante el proceso.
Veamos un ejemplo simple de uso
$ go mod graph
golearn github.com/246859/containers@v0.0.1
golearn github.com/246859/river@v0.1.0
golearn github.com/Jleagle/steam-go@v0.0.0-20230725082712-1053b441b1f2
golearn github.com/Jleagle/unmarshal-go@v0.0.0-20210227002040-694f544f9265
golearn github.com/KyleBanks/depth@v1.2.1
golearn github.com/Microsoft/go-winio@v0.6.1
golearn github.com/PuerkitoBio/purell@v1.1.1
golearn github.com/PuerkitoBio/urlesc@v0.0.0-20170810143723-de5bf2ad4578
golearn github.com/andeya/ameda@v1.5.3
golearn github.com/andeya/goutil@v1.0.1
golearn github.com/asaskevich/govalidator@v0.0.0-20230301143203-a9d515a09cc2
golearn github.com/buger/jsonparser@v1.1.1
golearn github.com/bwmarrin/snowflake@v0.3.0
golearn github.com/bytedance/go-tagexpr/v2@v2.9.11
......vendor
$ go help mod vendor
usage: go mod vendor [-e] [-v] [-o outdir]Vendor era una alternativa a gopath antes de que gomod fuera lanzado, cada proyecto go tenía un directorio vendor, que almacenaba cada dependencia del proyecto por separado en el formato domain/user/project, como el hinchado node_module de nodeJs donde cada dependencia del proyecto se almacena por separado, esta forma de gestión de dependencias ahora parece bastante estúpida, pero en ese momento no había una mejor solución, y la razón por la que se retuvo vendor es porque go se adhiere a la promesa de compatibilidad con versiones anteriores, algunos proyectos antiguos incluyendo el código fuente de go todavía pueden estar usando vendor.
Volviendo al tema, vendor es un subcomando de go mod, puede exportar las dependencias globales referenciadas por el módulo actual al directorio vendor.
$ go mod vendor -h
usage: go mod vendor [-e] [-v] [-o outdir]
Run 'go help mod vendor' for details.Tiene los siguientes parámetros
-o:especifica la ruta de la carpeta de salida-v:muestra cada dependencia-e:no sale cuando ocurre un error, continúa
Veamos un ejemplo, primero usa go list -m all para ver las dependencias referenciadas por el proyecto actual
$ 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.1Exportar al directorio vendor actual
$ go mod vendor -v -e -o vendor
# github.com/davecgh/go-spew v1.1.1
## explicit
github.com/davecgh/go-spew/spew
# github.com/pkg/errors v0.9.1
## explicit
github.com/pkg/errors
# github.com/pmezard/go-difflib v1.0.0
## explicit
github.com/pmezard/go-difflib/difflib
# github.com/stretchr/testify v1.8.4
## explicit; go 1.20
github.com/stretchr/testify/assert
# gopkg.in/yaml.v3 v3.0.1
## explicit
gopkg.in/yaml.v3La estructura del directorio después de exportar es la siguiente
└─vendor
├─github.com
│ ├─davecgh
│ │ └─go-spew
│ │ └─spew
│ ├─pkg
│ │ └─errors
│ ├─pmezard
│ │ └─go-difflib
│ │ └─difflib
│ └─stretchr
│ └─testify
│ └─assert
└─gopkg.in
| └─yaml.v3
|
|--modules.txtEl archivo modules.txt es el archivo que describe todas las dependencias, similar al actual go.mod.
verify
$ go help mod verify
usage: go mod verifyEste comando verificará si las dependencias del proyecto han sido modificadas desde que se descargaron localmente. Por ejemplo, si no hay problemas, mostrará all modules verified
$ go mod verify
all modules verifiedDe lo contrario, reportará dónde ocurrieron los cambios, y terminará el comando con un estado anormal. Por ejemplo
$ go mod verify
gorm.io/gorm v1.25.5: dir has been modified (/go/mod/libs/gorm.io/gorm@v1.25.5)why
$ go help mod why
usage: go mod why [-m] [-vendor] packages...Explica por qué este paquete es dependencia, en realidad muestra el grafo de dependencias relacionado con él. Por ejemplo
$ go mod why gorm.io/gorm
# gorm.io/gorm
golearn
gorm.io/gormPor defecto solo analiza las importaciones desde main, agregando el parámetro -m puede analizar la situación de importación de cada paquete.
work
El comando work es una herramienta de desarrollo local para la gestión de múltiples módulos go
$ go work help
Work provides access to operations on workspaces.
Note that support for workspaces is built into many other commands, not
just 'go work'.
The commands are:
edit edit go.work from tools or scripts
init initialize workspace file
sync sync workspace build list to modules
use add modules to workspace file
vendor make vendored copy of dependencies
Use "go help work <command>" for more information about a command.init
El subcomando init se usa para inicializar un workspace, este comando creará un archivo llamado go.work
$ go work init -h
usage: go work init [moddirs]
Run 'go help work init' for details.Acepta el parámetro [moddirs] para especificar qué directorios de módulos incluir en la gestión, por ejemplo
$ go work init ./service ./apiuse
El subcomando use se usa para agregar directorios de módulos al go.work para su gestión
$ 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.Acepta [moddirs] como parámetro, y también tiene un -r que indica búsqueda recursiva de módulos en la ruta [moddirs], por ejemplo
$ go work use -r ./oss-api ./multi_modulesedit
El subcomando edit tiene la misma función que go mod edit, ambos son interfaces de línea de comandos dejadas para que otras herramientas y scripts operen.
$ 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 directoriesLos parámetros son los siguientes
-fmt, formatea el archivogo.work-use,-dropuse, agregan y eliminan rutas de módulos-replace=old[@v]=new[@v],-dropreplace=old[@v]=new[@v], usados para agregar y eliminar módulos a reemplazar-go,-toolchain=name, especifican la versión de go, y especifican el toolchain a usar-print, imprime las modificaciones finales, no escribe en el archivo-json, muestra en formatojson, no puede existir al mismo tiempo que-print, el tipo de estructura correspondiente es el siguientegotype 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 }
Algunos ejemplos de uso, formatear la salida
$ go work edit -fmt -print
go 1.22.0
use (
./ab/cd
./auth
./user
)Salida json
$ go work edit -fmt -json
{
"Go": "1.22.0",
"Use": [
{
"DiskPath": "./ab/cd"
},
{
"DiskPath": "./auth"
},
{
"DiskPath": "./user"
}
],
"Replace": null
}sync
El subcomando sync se usa para sincronizar la lista de compilación del workspace de vuelta a los módulos del workspace.
$ go help work sync
usage: go work sync
Sync syncs the workspace's build list back to the
workspace's modulesEste proceso ocurre principalmente después de completar el desarrollo local, cuando cada módulo ya ha completado el trabajo de publicación, en este momento al usar sync, actualizará las dependencias en el go.mod de todos los módulos del workspace según las dependencias de cada módulo, para que no tengamos que actualizar manualmente.
vendor
El comando vendor hará una copia de todas las bibliotecas dependientes de los módulos en el workspace al directorio vendor.
$ go work help vendor
usage: go work vendor [-e] [-v] [-o outdir]La función es la misma que go mod vendor, no se hará más explicación.
vet
El comando vet es una herramienta de comprobación de errores estáticos del código fuente del lenguaje go, como las herramientas lint de otros lenguajes, como Eslint.
$ go vet -h
usage: go vet [build flags] [-vettool prog] [vet flags] [packages]
Run 'go help vet' for details.
Run 'go tool vet help' for a full list of flags and analyzers.
Run 'go tool vet -help' for an overview.Primero veamos un ejemplo simple, tenemos el siguiente código fuente
$ cat main.go
package main
import "fmt"
func main(){
fmt.Println("hello world!"
}Ejecuta go vet sin ningún parámetro en el mismo directorio
$ go vet
vet: ./main.go:6:28: missing ',' before newline in argument list (and 1 more errors)vet reportará qué archivo qué línea tiene qué problema. Soporta flags de compilación como parámetros, como -n y -x, soporta paquetes, carpetas, nombres de archivo como parámetros.
$ go vet .
$ go vet main.go
$ go vet ./cmd
$ go vet runtimeA través del siguiente comando puedes ver sus parámetros más detallados y explicaciones.
$ 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
......El comando go tool vet no se puede usar directamente para comprobar el código, debes usar go vet. El [vet flag] en los parámetros de go vet soporta configurar analizadores de código, los valores disponibles son los siguientes
asmdecl comprueba si los archivos ensamblador no coinciden con las declaraciones go
assign comprueba si hay variables inútiles
atomic comprueba si se rompe la atomicidad al usar sync/atomic
bools comprueba si se usan incorrectamente operadores lógicos
buildtag comprueba build tag
cgocall comprueba comportamientos que violan las reglas de paso de punteros cgao
composites comprueba estructuras compuestas no inicializadas, como map, chan
copylocks comprueba si se ha producido una copia de valor de un bloqueo
directive comprueba las directivas del toolchain go
errorsas comprueba si se pasa un tipo no puntero o no error a errors.As
framepointer comprueba si el código ensamblador optimizado borra el frame pointer antes de guardarlo
httpresponse comprueba si se usa incorrectamente httpresponse
ifaceassert comprueba las aserciones de tipo de interfaz a interfaz
loopclosure problemas de referencia de variables de bucle
lostcancel context.WithCancel no usa la función cancel
nilfunc comprueba si hay comparaciones inútiles entre funciones y nil
printf comprueba si los parámetros de formato de printf son correctos
shift comprueba si hay desplazamientos iguales o superiores al ancho de enteros
sigchanyzer comprueba chan os.Signal sin búfer
slog comprueba llamadas de registro estructurado no válidas
stdmethods comprueba si las firmas de métodos de interfaz conocidos son correctas
stringintconv comprueba la conversión de entero a cadena
structtag comprueba si los tags de estructura son correctos
testinggoroutine comprueba si se usa goroutine para llamar a testing.Fatal en pruebas
tests comprueba errores comunes de uso en pruebas y ejemplos
timeformat comprueba si el formato de (time.Time).Format o time.Parse es correcto
unmarshal pasa tipos no puntero o no interfaz a unmarshal
unreachable comprueba código inalcanzable
unsafeptr comprueba conversiones incorrectas de uintptr a unsafe.Pointer
unusedresult comprueba valores de retorno de función no usadosTodos son analizadores que analizan un punto específico, por ejemplo el analizador timeformat comprueba si el formato de llamada de time.Format cumple con la sintaxis correcta. Por defecto, todos los analizadores anteriores están habilitados, para habilitar individualmente puedes usar el siguiente formato
$ go vet -timeformat main.goPara deshabilitar individualmente
$ go vet -timeformat=false main.goEl código fuente de estos analizadores está ubicado en cmd/vendor/golang.org/x/tools/go/analysis/passes, cada analizador es un problema común en el que el lenguaje go puede caer fácilmente, por lo que se recomienda encarecidamente usar el comando vet para comprobar tu código. Además de estos, también soporta algunos analizadores externos, como shadows, que es responsable de detectar problemas de ocultamiento de variables nombradas con variables cortas, como es externo, necesitas descargarlo con go install
$ go install golang.org/x/tools/go/analysis/passes/shadow/cmd/shadow@latestEl formato de uso es el siguiente
$ go vet -vettool=$(which shadow)test
$ go test -h
usage: go test [build/test flags] [packages] [build/test flags & test binary flags]
Run 'go help test' and 'go help testflag' for details.El comando test es el comando que proporciona la funcionalidad de pruebas en el toolchain del lenguaje go, esta funcionalidad es bastante importante, para un software, pruebas completas son indispensables. Aquí solo se presenta brevemente cómo usar el comando test, para aprender más sobre pruebas, visita: 测试
Además de soportar los parámetros de compilación del comando build, test también soporta los siguientes parámetros
-args, parámetros de entrada del programa-c, compila el archivo binario de pruebas del paquete actual al directorio actual pero no lo ejecuta, nombrado comopkg.test-exec, ejecuta algunos otros comandos antes de que comiencen las pruebas-json, el estilo de salida de las pruebas se convierte en json-o, especifica el nombre de ruta del archivo binario de pruebas
También soporta muchos testflag, usa el comando help para ver todos los testflag
$ go help testflag
`go test` 命令既接受作用于 `go test` 本身的标志,
也接受作用于生成的测试二进制文件的标志。
`go test` 命令识别以下标志,并用于控制任何测试的执行:
-bench regexp
-benchtime t
-count n
......Se presentan algunos comúnmente usados
-v, muestra el resultado de cada caso de prueba.-timeout duration, tiempo de espera de ejecución de pruebas-skip regexp, salta los casos de prueba especificados-short, hace que los casos de prueba que tardan mucho tiempo en ejecutar acorten su tiempo de ejecución-shuffle, desordena el orden de ejecución de todos los casos de prueba-run regexp, ejecuta los casos de prueba especificados-list regexp, lista cada caso de prueba-cpu 1,2,4, especifica el número de cpu-count n, especifica cuántas veces se ejecuta cada caso de prueba
El uso más simple es, sin ningún parámetro, ejecutará todos los casos de prueba en el paquete actual, y mostrará los resultados.
$ ls *_test.go
hello_test.go
$ go test
PASS
ok golearn 0.522sEspecificar un archivo de prueba determinado
$ go test hello_test.go
ok command-line-arguments 0.041sAgregando el parámetro -v puedes ver una salida más detallada, es bastante común.
$ go test -v hello_test.go
=== RUN TestHello
hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok command-line-arguments 0.041sEspecificar un caso de prueba determinado
$ go test -v -run TestHello
=== RUN TestHello
hello_test.go:6: hello world!
--- PASS: TestHello (0.00s)
PASS
ok golearn 0.028sAl realizar pruebas, el comando test tiene dos modos, primero hablemos del modo de carpeta, cuando se ejecuta el comando test sin el parámetro package, se ejecutará en modo de carpeta, por ejemplo los siguientes comandos
$ go test
$ go test -vEn este modo, se deshabilita la caché de pruebas. El otro modo es el modo de lista, cuando el parámetro package no está vacío, se realizarán pruebas en modo de lista, la diferencia con el anterior es si se habilita la caché de pruebas. Por ejemplo los siguientes
$ go test -v .
$ go test -v ./...
$ go test .
$ go test -v net/httpEn el modo de lista, go compilará los archivos de prueba de cada paquete bajo el paquete especificado en archivos binarios y los ejecutará, para evitar ejecutar pruebas repetidamente, go por defecto almacenará los resultados en caché, no se recompilará en la segunda ejecución. El uso de los siguientes parámetros habilitará la caché por defecto
-benchtime-cpu-list-parallel-runshort-timeout-failfast-v
Usando otros parámetros además de estos se puede deshabilitar la caché, el método recomendado por el oficial es usar -count=1 para deshabilitar la caché. Por ejemplo
$ go test -v -count=1 ./...Directivas
A diferencia de los comandos, las directivas de go existen en forma de código duro en los archivos fuente, tienen otro nombre más técnico: pragma directives.
El compilador y el linker cambiarán su comportamiento debido a ellas, logrando así el efecto de controlar la compilación, es algo similar a las macros en c, por supuesto, no todas las directivas se usan para afectar la compilación, algunas se usan para comportamientos funcionales, por ejemplo la directiva generate generalmente se usa para la funcionalidad de generación de código. Estas directivas generalmente existen en forma de comentarios, y con el prefijo //go:, sin ningún espacio en el medio, por ejemplo la directiva //go:generate. Todos los tipos de directivas se dividen en dos categorías
- Directivas funcionales, estas son directivas funcionales proporcionadas por go que se pueden usar libremente, como
generate,embed,build. - Directivas del compilador, estas directivas se deben usar con precaución, su uso indiscriminado puede causar resultados impredecibles.
Excepto las directivas funcionales, la mayoría de las directivas solo pueden actuar sobre firmas de funciones. Para las directivas del compilador puedes ejecutar el comando go doc compile para ver sus directivas. Para todas las directivas, puedes encontrar información sobre ellas en cmd/compile/internal/ir/node.go: 440.
generate
$ go help generate
usage: go generate [-run regexp] [-n] [-v] [-x] [build flags] [file.go... | packages]La directiva generate como su nombre indica tiene que ver con la generación, generalmente su función es ejecutar comandos que generarán código y actualizarán el código fuente, pero en realidad puede ejecutar cualquier comando. Además, la directiva generate es diferente de otras directivas, tiene un comando dedicado que se puede usar para ejecutar todas las directivas generate en los archivos fuente. Puede tomar nombres de archivo o nombres de paquetes como parámetros de entrada para indicar qué archivos ejecutar las directivas generate, estos son sus otros parámetros.
-run=regex, ejecuta las directivas generate especificadas-skip=regex, salta las directivas generate especificadas-n, imprime los comandos que se ejecutarán-x, imprime los comandos ejecutados durante el proceso-v, muestra los archivos procesados
Además, los comandos ejecutados en la directiva generate también soportan los siguientes parámetros integrados
$GOARCH, arquitectura de cpu$GOOS, sistema operativo$GOFILE, nombre de archivo$GOLINE, número de línea$GOPACKAGE, nombre del paquete$GOROOT, go root$DOLLAR, símbolo de dólar$PATH, variable de entorno path
Veamos un ejemplo, no hay código, solo un comentario
package main
//go:generate echo "hello world!"Ejecuta el comando
$ go generate .
hello world!Este ejemplo ejecuta un comando go
package main
//go:generate go versionEjecuta el comando
$ go generate .
go version go1.21.3 windows/amd64La directiva generate se puede usar para ejecutar cualquier comando, como swagger para generar documentación de API, o Wire para generar código IOC. Sin embargo, esta directiva no es adecuada para ejecutar comandos particularmente complejos, es adecuada para ejecutar comandos cortos, si hay necesidades complejas puedes usar scripts o makefile para reemplazar.
embed
La directiva embed es nueva en 1.16, su función es que puede empaquetar archivos estáticos junto en el archivo binario, como plantillas HTML. Su formato es el siguiente
//go:embed patternpattern puede ser una expresión glob, o una carpeta o un archivo específico. Veamos un ejemplo
package main
import "embed"
//go:embed *
var static embed.FSLa directiva embed requiere que esté encima de una variable global de tipo embed.Fs, ten en cuenta que debe ser una variable global, y para usarla debes importar el paquete embed, en este ejemplo, * representa que todos los archivos en la carpeta actual se empaquetarán en el archivo binario, pero no permitirá que existan carpetas que empiecen por ..
El siguiente ejemplo muestra cómo leer contenido de archivos embebidos
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))
}Solo tiene tres métodos, usarlo es similar a un sistema de archivos normal, y como implementa la interfaz io/Fs, también se puede pasar como objeto Fs.
func (f FS) Open(name string) (fs.File, error)
func (f FS) ReadFile(name string) ([]byte, error)
func (f FS) ReadDir(name string) ([]fs.DirEntry, error)El siguiente ejemplo muestra cómo embeber archivos html a través de la directiva embed, y acceder a través de un servicio http.
package main
import (
"embed"
"net/http"
)
//go:embed index.html
var htmlFs embed.FS
func main() {
http.Handle("/", http.FileServer(http.FS(htmlFs)))
http.ListenAndServe(":8080", http.DefaultServeMux)
}El resultado del acceso es el siguiente
$ curl -s -GET 127.0.0.1:8080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world!</title>
</head>
<body>
<H1>Hello World!</H1>
<script>
alert("hello world!");
</script>
</body>
</html>La directiva embed también soporta que el tipo de variable global pueda ser []byte, por ejemplo el siguiente ejemplo
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)
}El efecto que logra es similar al ejemplo anterior.
$ curl -s -GET 127.0.0.1:8080
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>hello world!</title>
</head>
<body>
<H1>Hello World!</H1>
<script>
alert("hello world!");
</script>
</body>
</html>build
En la sección build-control de compilación, se explicó cómo usar la directiva // +build para controlar el comportamiento de compilación. La directiva //go:build es nueva en 1.17, con la intención de reemplazar la directiva anterior, pero ahora en 1.21 todavía no ha sido reemplazada, probablemente coexistirán en el futuro, sobre esta nueva directiva, la documentación oficial también tiene una introducción: build constraints. Su función no es diferente de la anterior, pero la sintaxis es más estricta, soporta expresiones booleanas, veamos un ejemplo
//go:build (linux && 386) || (darwin && !cgo)
package pkg_nameEsta forma es mucho más legible que la anterior.
line
La directiva line afectará el número de línea, número de columna, y el nombre de archivo de la siguiente línea, su función se limita a esto, la mayoría de las veces puede ser usada para depurar errores, etc. Por ejemplo, cuando ocurre un error, cambiará la información que muestra el compilador.
package main
var a undefinedType
func main() {
}Normalmente, el compilador mostrará
.\main.go:3:7: undefined: undefinedTypePero si se usa la directiva line, es diferente
package main
//line abc.go:10:100
var a undefinedType
func main() {
}Entonces su salida será
abc.go:10:106: undefined: undefinedTypeY por razones históricas, la directiva line es también la única directiva cuyo uso es diferente de otras directivas. Su formato es
//line filename:line:columnSe puede ver que no necesita go: como prefijo.
linkname
Esta operación de directiva se puede usar para enlazar funciones o variables globales de otros paquetes, incluso si son tipos privados, esta operación aparece frecuentemente en la biblioteca estándar especialmente en runtime, hay algunas funciones que no tienen cuerpo de función, esto se logra a través de esta forma, otra parte de las funciones con cuerpo vacío se implementan en ensamblador. Veamos su uso, el formato de uso es el siguiente
//go:linkname nombre del tipo enlazado tipo a enlazarY antes de usar, debes importar el paquete unsafe. Veamos un ejemplo simple de enlace a un tipo privado en la biblioteca estándar
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")))
}Salida
15395306441938000233Enlaza la función privada runtime.memhash con nuestra propia función declarada, esta función no tiene cuerpo de función, solo una firma, solo sirve como portador. La función de memhash es dado un puntero, semilla de hash, y offset de memoria, calcular el valor hash basándose en la memoria. Este proceso de enlace se completa en tiempo de compilación.
Si no es de la biblioteca estándar, la situación es algo diferente, por ejemplo hay una función test en el paquete example, antes de enlazar primero debes importar anónimamente este paquete.
package example
// Un tipo privado, no accesible desde fuera.
func test() string {
return "a"
}package main
import (
"fmt"
_ "golearn/example"
_ "unsafe"
)
//go:linkname test golearn/example.test
func test() string
func main() {
fmt.Println(test())
}Salida
aSe puede ver que el enlace ha sido exitoso, este método puede evitar el sistema de módulos de go y hacer lo que quiera, pero no se recomienda su uso a gran escala, a menos que sepas lo que estás haciendo.
noinline
La directiva noinline indica que una función prohíbe la optimización de inline, incluso si es muy simple. Veamos un ejemplo simple
package main
func val() string {
return "val"
}
func main() {
var c = val()
_ = c
}val es una función muy simple, su función es devolver un literal de cadena, como es demasiado simple y su resultado siempre es predecible, al compilar será optimizada por el compilador a la siguiente forma
package main
func main() {
var c = "val"
_ = c
}Veamos su forma en ensamblador, se puede ver que no se encontró la llamada a la función 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)
RETAhora agreguemos la directiva noinline
package main
//go:noinline
func val() string {
return "val"
}
func main() {
var c = val()
_ = c
}Veamos su forma en ensamblador
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
RETEsta vez puedes ver muy claramente la llamada main.val, y esta es exactamente la función que noinline desempeña, evitar el inline de funciones durante la optimización del compilador.
nospilit
La directiva nospilit sirve para saltar la detección de desbordamiento de pila. Como el modelo de programación concurrente de go es de programación preventiva, supongamos que una función ejecutará código muy de bajo nivel, no es apropiado que otras corrutinas sean preventadas al llamar a esta función, se puede usar esta directiva para indicarlo.
//go:nosplit
func nospilitFn()Después de usar esta directiva, tampoco se realizará el crecimiento de pila.
noescape
noescape, por su nombre puedes adivinar fácilmente que tiene que ver con el escape, su función es indicar que la función actual no tendrá comportamiento de escape de memoria, después de ejecutarse todos los recursos son recuperados, y esta función debe tener solo una firma sin cuerpo de función, en este caso generalmente la implementación de la función es en ensamblador.
Por ejemplo, memhash usada anteriormente usará esta directiva
//go:noescape
//go:linkname memhash runtime.memhash
func memhash(p unsafe.Pointer, h, s uintptr) uintptrDe esta manera, el compilador no realizará análisis de escape en ella, la premisa es que debes garantizar que no ocurrirá escape, si ocurre, no se sabe qué consecuencias habrá.
uintptrescapes
La directiva uintptrescapes indica que el parámetro de tipo uinptr en esta función ha sido convertido a un valor de puntero y ha escapado al heap, y debe mantenerse vivo. Esta directiva generalmente se usa para algunas llamadas de sistema de bajo nivel, la mayoría de las veces no necesitas conocerla.
//go:uintptrescapes
func nospilit(ptr uintptr) uintptrAnteriormente debería haber una directiva notinheaps usada para indicar que un tipo no permite asignar memoria en el heap, no se sabe en qué versión fue eliminada.
norace
La directiva norace indica que el acceso a memoria de una función ya no necesita análisis de race condition, generalmente se usa cuando se ejecuta código de bajo nivel que no es adecuado para análisis de race condition.
//go:norace
func low_level_code(ptr uintptr) uintptrTIP
También hay algunas directivas que están restringidas para ser usadas solo por el paquete runtime, externamente no se pueden usar, involucran cosas más profundas, para conocerlas puedes ver Runtime-only compiler directives.
