Gestión de paquetes de Golang1.5 a Golang1.12: proveedor de golang para ir a mod

1. Introducción

Golang Es un lenguaje estático de alto nivel que existe desde hace diez años. Fue lanzado oficialmente en 2009, y luego, en uno o dos años más recientes, de 2017 a 2018, de repente se incendió. O&M / Live / Short Video / Blockchain ...

Golang La sintaxis es simple y la simplicidad es la complejidad. El núcleo de la construcción del software es simplificar las cosas complejas y manejar la complejidad.

Como uno gopher, debemos conocer su gestión de paquetes, para que podamos racionalizar la estructura del código y hacer un buen trabajo en la gestión de proyectos. ( gopher: Gopher)

2. Antes de GOPATH / Golang 1.5

GolangLa gestión de paquetes para que la población tiene la enfermedad, se inicia con GOPATHdepender de gestión de bibliotecas, especialmente simple y crudo.

Si la variable de entorno:

export GOROOT=/home/love/go
export GOPATH=/home/love/code
export GOBIN=$GOROOT/bin

Lo anterior GOROOTse refiere a Golang编译器以及其工具链,基础源码库la directorio se encuentra, GOPATHque es el código de la ubicación definida por el usuario.

La GOPATHsiguiente estructura:

├── src
    └── github.com
        └── hunterhug
            └── rabbit
                └── a
                    └── a.go
                └── main.go
├── bin
├── pkg 

El paquete de desarrollo que escribimos tiene una ruta simple y fácil de entender. Por ejemplo, mi paquete se llama github/hunterhug/rabbit, entonces la estructura es la misma que la anterior.

Entramos en el rabbitdirectorio, main.goel código:

package main
import "github/hunterhug/rabbit/a"

func main(){
  ...
}

Luego go build, entonces, en la búsqueda de paquetes, from'll GOPATH srcempezar a buscar a continuación, tales como rabbitel bajo paquete main.gose basó github/hunterhug/rabbit/a, entonces primero desde srcabajo por la costura por el camino de encontrar, y luego encontrar, la última generación, y el nombre del paquete github/hunterhug/rabbitcomo el llamado rabitbinario.

Si somos go install, entonces este se guardará en el archivo binario GOBINcaso (si no está presente GOBIN, será salvo en GOPATH bincaso). Si queremos compilar el paquete que falta, se go get -vdescargará las dependencias de código fuente a GOPATH srcla siguiente, y luego GOPATH pkggenera una biblioteca estática del directorio de paquetes (con la próxima no se necesita para construir desde el código fuente, y el recuento de caché).

Pero cuando no se puede encontrar nuestro paquete:

love@love:~/code/src/github.com/hunterhug/fafacms$ go build
core/server/server.go:4:2: cannot find package "github.com/gin-contrib/cors" in any of:
        /home/love/go/src/github.com/gin-contrib/cors (from $GOROOT)
        /home/love/code/src/github.com/gin-contrib/cors (from $GOPATH)

Descubrimos que, de hecho, es ir GOROOThacia abajo para encontrar el paquete, el paquete no se puede encontrar, van GOPATHencontrar, me trasladaron a llorar! Por ejemplo, nuestra GOPATHpróxima construcción de un fmtpaquete:

package fmt

func PPrintln() {
    print("i am diy fmt")
}

Pero queremos hacer referencia a esta biblioteca y main.gousar:

package main
import fmt
func main(){
  fmt.PPrintln()
}

¡No puedo encontrarlo, 2333! Por lo tanto, GOPATHbajo el paquete sería mejor no GOROOTla biblioteca estándar bajo el mismo nombre!

Nos fijamos en GOROOTla estructura:

├── src
    └── time
    └── fmt
├── bin
├── pkg 

Este no es nuestro GOPATHgusta, sí, ahora Golang编译器es un auto-compilado, se utiliza Golangpara escribir Golang编译器, sus compiladores y productos intermedios, las bibliotecas básicas, y para mantener GOPATHun cabello lo más fluida.

Sin embargo, hay versiones para diferentes paquetes dependientes. ¿Qué sucede si la versión cambia? Esto requiere gestión manual.

3. Vendedor / Bienes1.5 以后

Gestionar su propia versión de la biblioteca, creo que es poco probable que, después de todo, Javano maven, Pythonno pip, PHPno compose, NodeJsno npm.

Así que desde Golang1.5la puesta en marcha comenzó vendormecanismo de carpeta ( vendor: vendedores / vendedores ambulantes).

De Golang1.6oficialmente abrir esta función.

Por ejemplo, nuestro paquete llamado awesomeProjecten GOPATHvirtud de la construcción:

├── src
    └── awesomeProject
        └── vendor
            └── fmt
                └── fmt.go
        └── main.go
├── pkg 

Entre ellos main.go:

package main

import "fmt"

func main() {
    fmt.PPrintln()
}

Entramos en el awesomeProjectdirectorio y go build, aun con éxito.

No va a ser como no estallado en lo anterior vendorhace referencia directa cuando GOROOTel paquete estándar, que finalmente puede utilizar un paquete estándar y un paquete del mismo nombre, y que está en el main.gomismo directorio vendorde abajo!

Ahora, nos importencontramos en el mismo paquete de primer nivel se vendormira, y luego no se puede encontrar bajo el método anterior.

Si nosotros maincambiamos la referencia a un paquete que no exista b:

package main

import (
    "b"
)

func main() {
    b.P()
}

Entonces go buildConsejo:

main.go:4:2: cannot find package "b" in any of:
        /home/love/code/src/awesomeProject/vendor/b (vendor tree)
        /home/love/go/src/b (from $GOROOT)
        /home/love/code/src/b (from $GOPATH)

Si en este momento nos estamos un poco díscolo en GOPATH srcla creación de un vacío debajo de vendoruna carpeta, se le pide:

main.go:4:2: cannot find package "b" in any of:
        /home/love/code/src/awesomeProject/vendor/b (vendor tree)
        /home/love/code/src/vendor/b
        /home/love/go/src/b (from $GOROOT)
        /home/love/code/src/b (from $GOPATH)

Bueno, encontramos que el método de carga es:

包同目录下的vendor
GOPATH src 下的vendor
GOROOT src
GOPATH src

Si GOROOTy GOPATHconstruido a vendorlo que va a pasar? No dejamos de lastimar, 233. .

Bueno, la pregunta ahora es vendorcómo el burbujeo, si yo main.gocité vendor/b, mientras que bel interior del paquete se refiere a un cpaquete. En este punto vendor/bserá cómo encontrar la biblioteca?

├── src
    └── awesomeProject
        └── vendor
            └── b
                └── b.go
        └── main.go
├── pkg 

Ahora vendor/b/b.golos contenidos:

package b

import "c"

func P() {
    print(" i am vendor b\n")
    c.P()
}

Entramos en los awesomeProjectproyectos go build, aparece:

vendor/b/b.go:3:8: cannot find package "c" in any of:
    /home/love/code/src/awesomeProject/vendor/c (vendor tree)
    /home/love/code/src/vendor/c
    /home/love/go/src/c (from $GOROOT)
    /home/love/code/src/c (from $GOPATH)

Ahora el proceso de carga es:

包同目录的包(即b包同目录看看有没有c包)
GOPATH src 下的vendor
GOROOT src
GOPATH src

En este momento estamos vendor/ben una construcción vacía vendor:

├── src
    └── awesomeProject
        └── vendor
            └── b
                └── vendor
                └── b.go
        └── main.go
├── pkg 

En el awesomeProjectproyecto y luego go buildhabrá:

vendor/b/b.go:3:8: cannot find package "c" in any of:
    /home/love/code/src/awesomeProject/vendor/b/vendor/c (vendor tree)
    /home/love/code/src/awesomeProject/vendor/c
    /home/love/code/src/vendor/c
    /home/love/go/src/c (from $GOROOT)
    /home/love/code/src/c (from $GOPATH)

Si nos encontramos con el anterior cpaquete, empatía en cllave en mano vacía vendor:

├── src
    └── awesomeProject
        └── vendor
            └── b
                └── vendor
                    └── c
                        └── vendor
                        └── c.go
                └── b.go
        └── main.go
├── pkg 

Pero cel paquete de c.goreferencias inexistente dpaquete:

package c

import "d"

func P() {
    d.P()
}

En el awesomeProjectproyecto y luego go buildhabrá:

vendor/b/vendor/c/c.go:3:8: cannot find package "d" in any of:
    /home/love/code/src/awesomeProject/vendor/b/vendor/c/vendor/d (vendor tree)
    /home/love/code/src/awesomeProject/vendor/b/vendor/d
    /home/love/code/src/awesomeProject/vendor/d
    /home/love/code/src/vendor/d
    /home/love/go/src/d (from $GOROOT)
    /home/love/code/src/d (from $GOPATH)

Descubrimiento, encontrar el paquete vendorestá burbujeando, un paquete de referencias otro paquete, echar un vistazo el mismo catálogo vendorque hay bajo este paquete, si no toda la parte trasera manera en el suelo vendorpara ver si no hay, entonces al siguiente nivel
vendor, hasta GOPATH src/vendor.

Entonces ahora el proceso de carga es:

包同目录下的vendor
包目录向上的最近的一个vendor
...
GOPATH src 下的vendor
GOROOT src
GOPATH src

Resumen: ¡ vendorBurbuja! ! ! !

En este caso, podemos confiar en el paquete se colocan vendordebajo, y luego enviado al almacén, por lo que puede ahorrar tiempo tirón el paquete, y relativamente libre, se puede pensar cómo cambiar, se puede poner a una persona se ha suprimido githubel paquete en el vendorcaso. De esta manera, sigue siendo manual y no puede gestionar versiones dependientes.

Así que muchos de terceros, tales como glide, godep, govendorherramientas emergieron, el uso de estas herramientas se basan paquete debe tener una completa gitversión, a continuación, todo dependerá de la versión escrita en un archivo de configuración.

Por ejemplo godep:

go get -v github.com/tools/godep

Ejecutar bajo paquete

godep save 

Generada Godeps/Godep.jsondependiente de la versión, y se recoge en el paquete actual registro vendorbajo.

3. Después de ir mod / Go1.11

Golang 1.11Comenzó, se han definido experimentalmente puede no GOPATHfuncionar, y no oficial go modde soporte. Golang 1.12Esta característica también está formalizada.

Ahora con Golang1.12fueron:

go mod init
go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'

En donde GO111MODULE=autoun interruptor de encendido o apagado del soporte de módulo, que tiene tres valores posibles: off/ on/ autovalores por defecto auto.

  1. GO111MODULE=off, No admite módulos, igual que antes.
  2. GO111MODULE=onLos soportes de módulo, ignoradas GOPATHy vendorcarpetas, sólo se basan go.moddependencia de descarga.
  3. GO111MODULE=autoEl proyecto en GOPATH srcel exterior y el directorio raíz tiene go.mod un archivo abierto soportes de módulos.

Cuando se utiliza el módulo, GOPATH no tiene sentido, pero todavía dependerá tienda de descarga en GOPATH/src/model, será go installcomo resultado GOPATH/bin(si GOBINno existe)

Sacamos el proyecto GOPATH, luego:

go mod init

Aparece:

go: cannot determine module path for source directory /home/love/awesomeProject (outside GOPATH, no import comments)

Ahora main.golee:

package main // import "github.com/hunterhug/hello"

import (
    "b"
)

func main() {
    b.P()
}

Generará go.mod:

module github.com/hunterhug/hello

go 1.12

En este momento nosotros:

go build
build github.com/hunterhug/hello: cannot load b: cannot find module providing package b

Esta vez no se puede encontrar vendor, y que vienen junto con los parámetros:

go build -mod=vendor
build github.com/hunterhug/hello: cannot load c: open /home/love/awesomeProject/vendor/c: no such file or directory

Lágrimas de lágrimas derramadas, vendor¿qué hay de burbujear? activar el original go.mod, vendorbajo el paquete bno se puede encontrar b/vendorbajo el paquete c, sólo para encontrar uno, 2.333.333, esto es bueno o malo?

En general, vendoraquí son vendorpoco científico, godepy otras herramientas dependerá enderezar, para asegurarse de que sólo hay una vendor.

A continuación, go.modllevar a vendorimpactos que no se generan burbujas, no es muy grande, caseta movido hasta las lágrimas.

Ahora usémoslo correctamente go mod, en circunstancias normales:

省略N步

Aquí, y lo sentimos mucho para decir adiós, y ahora go modacaba de salir, probablemente será otra actualización, puede buscar Google u otros artículos en esta zona, o bien:

go help modules

Esta parte puede escribirse en detalle después de un tiempo.

El entorno de producción actual con go modno muy realista, recomiendo primero la definición GOPATHy vendoruso.

4. Use Docker para compilar Golang en múltiples etapas

Entorno de instalación demasiado duro, mi Dios, cada vez que he cargado medio ambiente, podemos utilizar el siguiente método So easypara cambiar en cualquier momento Golangla versión.

Si su Golangproyecto depende almacena en vendorla parte inferior, entonces podemos utilizar de varias etapas construida y envasados en recipientes de imagen, Dockefilede la siguiente manera:

FROM golang:1.12-alpine AS go-build

WORKDIR /go/src/github.com/hunterhug/fafacms

COPY core /go/src/github.com/hunterhug/fafacms/core
COPY vendor /go/src/github.com/hunterhug/fafacms/vendor
COPY main.go /go/src/github.com/hunterhug/fafacms/main.go

RUN go build -ldflags "-s -w" -o fafacms main.go

FROM alpine:3.9 AS prod

WORKDIR /root/

COPY --from=go-build /go/src/github.com/hunterhug/fafacms/fafacms /bin/fafacms
RUN chmod 777 /bin/fafacms
CMD /bin/fafacms $RUN_OPTS

¿Dónde github.com/hunterhug/fafacmsestá su proyecto. Uso golang:1.12-alpinepara compilar binario, y luego una imagen base binaria en: alpine:3.9Esta imagen es particularmente pequeña.

Compilar:

sudo docker build -t hunterhug/fafacms:latest .

Tenemos un espejo extra hunterhug/fafacms:latest , y es muy pequeño, solo unos pocos M.

Ejecutar:

sudo docker run -d  --net=host  --env RUN_OPTS="-config=/root/fafacms/config.json" hunterhug/fafacms

Sin embargo, si se utiliza cgo, por favor, Dockerfileleemos:

FROM golang:1.12 AS go-build

WORKDIR /go/src/github.com/hunterhug/fafacms

COPY core /go/src/github.com/hunterhug/fafacms/core
COPY vendor /go/src/github.com/hunterhug/fafacms/vendor
COPY main.go /go/src/github.com/hunterhug/fafacms/main.go

RUN go build -ldflags "-s -w" -o fafacms main.go

FROM bitnami/minideb-extras-base:stretch-r165 AS prod

WORKDIR /root/

COPY --from=go-build /go/src/github.com/hunterhug/fafacms/fafacms /bin/fafacms
RUN chmod 777 /bin/fafacms
CMD /bin/fafacms $RUN_OPTS

5. Resumen

Administrar dependencias, cómo compilar código en binario, es un proceso y hay muchos detalles. Lo anterior es mi experiencia, gracias por leer.

Publicado 14 artículos originales · ganó 0 · 100 visitas

Supongo que te gusta

Origin blog.csdn.net/m0_46803965/article/details/105563501
Recomendado
Clasificación