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
Golang
La gestión de paquetes para que la población tiene la enfermedad, se inicia con GOPATH
depender 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 GOROOT
se refiere a Golang编译器以及其工具链,基础源码库
la directorio se encuentra, GOPATH
que es el código de la ubicación definida por el usuario.
La GOPATH
siguiente 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 rabbit
directorio, main.go
el código:
package main
import "github/hunterhug/rabbit/a"
func main(){
...
}
Luego go build
, entonces, en la búsqueda de paquetes, from'll GOPATH src
empezar a buscar a continuación, tales como rabbit
el bajo paquete main.go
se basó github/hunterhug/rabbit/a
, entonces primero desde src
abajo por la costura por el camino de encontrar, y luego encontrar, la última generación, y el nombre del paquete github/hunterhug/rabbit
como el llamado rabit
binario.
Si somos go install
, entonces este se guardará en el archivo binario GOBIN
caso (si no está presente GOBIN
, será salvo en GOPATH bin
caso). Si queremos compilar el paquete que falta, se go get -v
descargará las dependencias de código fuente a GOPATH src
la siguiente, y luego GOPATH pkg
genera 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 GOROOT
hacia abajo para encontrar el paquete, el paquete no se puede encontrar, van GOPATH
encontrar, me trasladaron a llorar! Por ejemplo, nuestra GOPATH
próxima construcción de un fmt
paquete:
package fmt
func PPrintln() {
print("i am diy fmt")
}
Pero queremos hacer referencia a esta biblioteca y main.go
usar:
package main
import fmt
func main(){
fmt.PPrintln()
}
¡No puedo encontrarlo, 2333! Por lo tanto, GOPATH
bajo el paquete sería mejor no GOROOT
la biblioteca estándar bajo el mismo nombre!
Nos fijamos en GOROOT
la estructura:
├── src
└── time
└── fmt
├── bin
├── pkg
Este no es nuestro GOPATH
gusta, sí, ahora Golang编译器
es un auto-compilado, se utiliza Golang
para escribir Golang编译器
, sus compiladores y productos intermedios, las bibliotecas básicas, y para mantener GOPATH
un 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, Java
no maven
, Python
no pip
, PHP
no compose
, NodeJs
no npm
.
Así que desde Golang1.5
la puesta en marcha comenzó vendor
mecanismo de carpeta ( vendor
: vendedores / vendedores ambulantes).
De Golang1.6
oficialmente abrir esta función.
Por ejemplo, nuestro paquete llamado awesomeProject
en GOPATH
virtud 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 awesomeProject
directorio y go build
, aun con éxito.
No va a ser como no estallado en lo anterior vendor
hace referencia directa cuando GOROOT
el paquete estándar, que finalmente puede utilizar un paquete estándar y un paquete del mismo nombre, y que está en el main.go
mismo directorio vendor
de abajo!
Ahora, nos import
encontramos en el mismo paquete de primer nivel se vendor
mira, y luego no se puede encontrar bajo el método anterior.
Si nosotros main
cambiamos la referencia a un paquete que no exista b
:
package main
import (
"b"
)
func main() {
b.P()
}
Entonces go build
Consejo:
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 src
la creación de un vacío debajo de vendor
una 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 GOROOT
y GOPATH
construido a vendor
lo que va a pasar? No dejamos de lastimar, 233. .
Bueno, la pregunta ahora es vendor
cómo el burbujeo, si yo main.go
cité vendor/b
, mientras que b
el interior del paquete se refiere a un c
paquete. En este punto vendor/b
será cómo encontrar la biblioteca?
├── src
└── awesomeProject
└── vendor
└── b
└── b.go
└── main.go
├── pkg
Ahora vendor/b/b.go
los contenidos:
package b
import "c"
func P() {
print(" i am vendor b\n")
c.P()
}
Entramos en los awesomeProject
proyectos 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/b
en una construcción vacía vendor
:
├── src
└── awesomeProject
└── vendor
└── b
└── vendor
└── b.go
└── main.go
├── pkg
En el awesomeProject
proyecto y luego go build
habrá:
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 c
paquete, empatía en c
llave en mano vacía vendor
:
├── src
└── awesomeProject
└── vendor
└── b
└── vendor
└── c
└── vendor
└── c.go
└── b.go
└── main.go
├── pkg
Pero c
el paquete de c.go
referencias inexistente d
paquete:
package c
import "d"
func P() {
d.P()
}
En el awesomeProject
proyecto y luego go build
habrá:
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 vendor
está burbujeando, un paquete de referencias otro paquete, echar un vistazo el mismo catálogo vendor
que hay bajo este paquete, si no toda la parte trasera manera en el suelo vendor
para 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: ¡ vendor
Burbuja! ! ! !
En este caso, podemos confiar en el paquete se colocan vendor
debajo, 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 github
el paquete en el vendor
caso. De esta manera, sigue siendo manual y no puede gestionar versiones dependientes.
Así que muchos de terceros, tales como glide
, godep
, govendor
herramientas emergieron, el uso de estas herramientas se basan paquete debe tener una completa git
versió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.json
dependiente de la versión, y se recoge en el paquete actual registro vendor
bajo.
3. Después de ir mod / Go1.11
Golang 1.11
Comenzó, se han definido experimentalmente puede no GOPATH
funcionar, y no oficial go mod
de soporte. Golang 1.12
Esta característica también está formalizada.
Ahora con Golang1.12
fueron:
go mod init
go: modules disabled inside GOPATH/src by GO111MODULE=auto; see 'go help modules'
En donde GO111MODULE=auto
un interruptor de encendido o apagado del soporte de módulo, que tiene tres valores posibles: off
/ on
/ auto
valores por defecto auto
.
-
GO111MODULE=off
, No admite módulos, igual que antes. -
GO111MODULE=on
Los soportes de módulo, ignoradasGOPATH
yvendor
carpetas, sólo se basango.mod
dependencia de descarga. -
GO111MODULE=auto
El proyecto enGOPATH src
el exterior y el directorio raíz tienego.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/mod
el, será go install
como resultado GOPATH/bin
(si GOBIN
no 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.go
lee:
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
, vendor
bajo el paquete b
no se puede encontrar b/vendor
bajo el paquete c
, sólo para encontrar uno, 2.333.333, esto es bueno o malo?
En general, vendor
aquí son vendor
poco científico, godep
y otras herramientas dependerá enderezar, para asegurarse de que sólo hay una vendor
.
A continuación, go.mod
llevar a vendor
impactos 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 mod
acaba 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 mod
no muy realista, recomiendo primero la definición GOPATH
y vendor
uso.
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 easy
para cambiar en cualquier momento Golang
la versión.
Si su Golang
proyecto depende almacena en vendor
la parte inferior, entonces podemos utilizar de varias etapas construida y envasados en recipientes de imagen, Dockefile
de 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/fafacms
está su proyecto. Uso golang:1.12-alpine
para compilar binario, y luego una imagen base binaria en: alpine:3.9
Esta 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, Dockerfile
leemos:
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.