¿Qué significa go build build? (ir a construir frente a ir a instalar)

106

Los programadores nuevos de Go a menudo no saben o se confunden lo que hace el comando fundamental de compilación de Go.

¿Qué es exactamente el go buildy go installcomandos de construir y de dónde poner el resultado / salida?

icza
fuente
go build vs go install
Benyamin Jafari

Respuestas:

125

Lo que hace el gocomando depende de si lo ejecutamos para un paquete "normal" o para el especial"main" paquete .

Para paquetes

  • go build  construye su paquete y luego descarta los resultados .
  • go installbuilds luego instala el paquete en su $GOPATH/pkgdirectorio.

Para comandos (paquete main)

  • go build  construye el comando y deja el resultado en el directorio de trabajo actual .
  • go installcrea el comando en un directorio temporal y luego lo mueve a $GOPATH/bin.

A que pasar go build ?

Puede pasar paquetes a go buildpaquetes que desee compilar. También puede pasar una lista de.go archivos de un solo directorio, que luego se trata como la lista de archivos de origen que especifican un solo paquete.

Si no se proporcionan paquetes (rutas de importación), la compilación se aplica en el directorio actual.

Una ruta de importación puede contener uno o más "..."comodines (en cuyo caso es un patrón ). ...puede coincidir con cualquier cadena, por ejemplo, net/...coincide con el netpaquete y los paquetes que se encuentran en cualquiera de sus subcarpetas. El comando

go build ./...

a menudo se usa para construir el paquete en la carpeta actual y todos los paquetes que se descargan. Este comando emitido en la raíz de un proyecto crea el proyecto completo.

Para obtener más información sobre cómo especificar paquetes, ejecute go help packages.

Respecto a los módulos

El soporte preliminar para los módulos Go se introdujo en Go 1.11, y los módulos se volvieron predeterminados a partir de Go 1.13. Cuando la goherramienta se ejecuta desde una carpeta que contiene un go.modarchivo (o uno de los padres de la carpeta actual), la goherramienta se ejecuta en modo compatible con módulos (el modo heredado se llama modo GOPATH ).

En el modo de reconocimiento de módulos, GOPATH ya no define el significado de las importaciones durante una compilación, pero aún almacena las dependencias descargadas (en GOPATH / pkg / mod) y los comandos instalados (en GOPATH / bin, a menos que GOBIN esté configurado).

Al construir módulos, lo que se construye se especifica en la lista de construcción . La lista de compilación contiene inicialmente solo el módulo principal (el módulo que contiene el directorio donde gose ejecuta el comando), y las dependencias del módulo principal se agregan a la lista de compilación, de forma recursiva (también se agregan las dependencias de las dependencias).

Para obtener más información, ejecute go help modules.


Básicamente, puede usar go buildcomo verificación de que los paquetes se pueden construir (junto con sus dependencias) mientras que go installtambién (permanentemente) instala los resultados en las carpetas adecuadas de su $GOPATH.

go build terminará silenciosamente si todo está bien, y le dará mensajes de error si los paquetes no se pueden construir / compilar.

Siempre que la goherramienta instala un paquete o binario, también instala las dependencias que tenga, por lo que la ejecución go installtambién instalará los paquetes de los que depende su programa (disponibles públicamente, paquetes "go gettable"), automáticamente.

Para empezar, lea la página oficial Cómo escribir código Go .

Más información sobre la goherramienta: Command go

También puede obtener más ayuda ejecutando el siguiente comando:

go help build

También vale la pena señalar que a partir de Go 1.5 go installtambién se eliminan los ejecutables creados por go build( fuente ):

Si 'go install' (sin argumentos, es decir, el directorio actual) tiene éxito, elimine el ejecutable escrito por 'go build', si está presente. Esto evita dejar atrás un binario obsoleto ...

Para completar la lista, go runcompila su aplicación en una carpeta temporal e inicia ese binario ejecutable. Cuando la aplicación se cierra, limpia correctamente los archivos temporales.

Pregunta inspirada por Dave Cheney's What does go build build?

icza
fuente
1
parece extraño que go install no actualice el ejecutable si es idéntico al instalado previamente ... ¿alguna información aquí?
Scott Stensland
14

Por paquete:

go build: construye su paquete y luego descarta los resultados

Eso no será cierto después de Go 1.10 (Q1 2018), gracias a CL 68116 y CL 75473 . Vea este hilo , al que hago referencia aquí.

¿Qué construyen exactamente los comandos go buildy?go install

Siempre que la herramienta go instala un paquete o binario, también instala las dependencias que tenga, por lo que ejecutar go install también instalará los paquetes de los que depende su programa (disponibles públicamente, paquetes "go gettable"), automáticamente.

En realidad ... go installcambiará también con Go 1.10, además del nuevo caché:

El go installcomando " " ya no instala las dependencias de los paquetes nombrados ( CL 75850 ).

Si ejecuta " go install foo", lo único que se instala esfoo .

Antes variaba. Si las dependencias estaban desactualizadas, " go install" también instaló las dependencias.
La instalación implícita de dependencias durante " go install" causó mucha confusión y dolores de cabeza a los usuarios, pero anteriormente era necesario habilitar compilaciones incrementales.
Ya no.
Creemos que la nueva " install what I said" semántica será mucho más comprensible, especialmente porque está claro por los informes de errores que muchos usuarios ya los esperaban.
Para forzar la instalación de dependencias durante " go install", use el nuevo " go install -i" , por analogía con " go build -i" y " go test -i".

El hecho de que " go install" se utilizara para instalar las dependencias reconstruidas causaba confusión con mayor frecuencia junto con -a, que significa " force rebuild of all dependencies".
Ahora, " go install -a myprog" forzará una reconstrucción completa de todas las dependencias de myprog, así como de myprogsí mismo, pero solo myprogse instalará. (Por supuesto, todas las dependencias reconstruidas se guardarán en la memoria caché de compilación).
Hacer que este caso funcione de manera más comprensible es especialmente importante junto con el nuevo análisis de obsolescencia basado en contenido, porque ve buenas razones para reconstruir dependencias con más frecuencia que antes. , lo que habría aumentado la cantidad de confusión de "por qué se instalaron mis dependencias".
Por ejemplo, si ejecuta "go install -gcflags=-N myprog ", se instala unmyprogconstruido sin optimizaciones del compilador, pero ya no reinstala los paquetes que myprogusa desde la biblioteca estándar sin optimizaciones del compilador.

VonC
fuente
¿Lo go buildhace get? Tengo un error de compilación cannot find package "github.com/spf13/cobra" in any of:…. No sé cómo decirlo para conseguirlo. ¿Necesito obtener explícitamente?
ctrl-alt-delor
@ ctrl-alt-delor ¿Con qué versión de Go? ¿Su proyecto tiene un go.modarchivo?
VonC
go version go1.11.4 linux/amd64. No sé acerca de go.mod. Estoy reconstruyendo https://github.com/cbroglie/mustache/blob/master/cmd/mustache/main.go, es extraño ya que acabo de compilar todo el paquete, y estoy usando este ejemplo como base, y creé una versión más básica que funcionó (pero sin usar esta biblioteca). No veo cómo no se instaló con el paquete de bigote.
ctrl-alt-delor
@ ctrl-alt-delor, por lo que cobr se vende en github.com/cbroglie/mustache/tree/master/cmd/mustache/vendor/… . ¿Está su GOPATH configurado correctamente?
VonC
He descubierto lo que ya encontraste. El paquete está en un subdirectorio de proveedor: es por eso que no se instaló. Sin embargo, no sé por qué no lo instala ahora en build. O cómo usar el directorio de proveedores (si lo copio a mi directorio).
ctrl-alt-delor