Xiaobai aprende los conceptos básicos de go 03: comprende la estructura del proyecto Go

Primero echemos un vistazo a la estructura del primer proyecto Go: el lenguaje Go en sí. La estructura del proyecto Go ha sido muy estable desde el lanzamiento de la versión 1.0. Hasta ahora, la estructura de nivel superior del proyecto Go básicamente no ha cambiado significativamente.

A partir del compromiso del proyecto Go 1e3ffb0c (14.5.2019), la estructura del proyecto Go1.0 es la siguiente:

$ tree -LF 1 ~/go/src/github.com/golang/go
./go
├── api/
├── AUTHORS
├── CONTRIBUTING.md
├── CONTRIBUTORS
├── doc/
├── favicon.ico
├── lib/
├── LICENSE
├── misc/
├── PATENTS
├── README.md
├── robots.txt
├── src/
└── test/

Como proyecto de creación del lenguaje Go, el diseño de la estructura del proyecto Go tiene un significado de referencia importante para proyectos posteriores del lenguaje Go, especialmente la estructura bajo el directorio src en los primeros proyectos de Go, que posteriormente fue adoptada por la comunidad Go como la estructura del proyecto de la aplicación Go. Las plantillas se utilizan ampliamente.

Tome la estructura bajo el directorio src de la versión anterior de Go 1.3 como ejemplo.

$ tree -LF 1 ./src
./src
├── all.bash*
├── all.bat
├── all.rc*
├── clean.bash*
├── clean.bat
├── clean.rc*
├── cmd/
├── lib9/
├── libbio/
├── liblink/
├── make.bash*
├── make.bat
├── Make.dist
├── make.rc*
├── nacltest.bash*
├── pkg/
├── race.bash*
├── race.bat
├── run.bash*
├── run.bat
├── run.rc*
└── sudo.bash*

Con respecto a la estructura del directorio src anterior, el autor resume las siguientes tres características.

1) En el script de compilación del código 源文件放在src下面的顶层目录.

2) El directorio secundario cmd en src almacena el directorio principal de archivos ejecutables relacionados con la cadena de herramientas Go (como go, gofmt, etc.) y sus archivos fuente del paquete principal.

3) El directorio secundario pkg en src almacena los paquetes de los que depende cada programa de la cadena de herramientas en el cmd anterior, el tiempo de ejecución de Go y los archivos fuente de la biblioteca estándar de Go. Como sigue

$ tree -LF 1 ./pkg
./pkg
...
├── flag/
├── fmt/
├── go/
├── io/
├── log/
├── math/
...
├── syscall/
├── testing/
├── text/
├── time/
├── unicode/
└── unsafe/

Desde Go 1.3, el directorio src del proyecto Go ha sufrido varios cambios estructurales.

● La versión Go 1.4 elimina el directorio pkg en src/pkg/xxx en el árbol de fuentes de Go y usa src/xxx directamente en su lugar.

● La versión 1.4 de Go agrega un directorio interno en src para almacenar paquetes que no se pueden importar externamente y que solo son utilizados por el proyecto Go.

● La versión Go 1.6 agrega el directorio de proveedores en src, pero el proyecto Go en sí mismo habilitó el mecanismo de proveedores en la versión Go 1.7. El directorio de proveedores almacena las dependencias del proyecto Go en proyectos externos, principalmente los diversos paquetes en golang.org/x, incluidos net, text, crypto, etc. Los paquetes en este directorio se actualizarán cada vez que se lance una versión de Go.

● La versión Go 1.13 agrega go.mod y go.num en src, realizando la migración del módulo go del propio proyecto Go. Todos los paquetes del proyecto Go se colocan en el módulo denominado std, y los paquetes de los que depende siguen siendo los paquetes en golang.org/x. Esto puede considerarse como un cambio importante en la estructura del directorio del proyecto Go y en la gestión de paquetes.

// Go 1.13版本Go项目src下面的go.mod
module std
go 1.12
require (
golang.org/x/crypto v0.0.0-20200124225646-8b5121be2f68
golang.org/x/net v0.0.0-20190813141303-74dc4d7220e7
golang.org/x/sys v0.0.0-20190529130038-5219a1e1c5f8 // indirect
golang.org/x/text v0.3.2 // indirect
)

El siguiente es el diseño completo del directorio src en la versión Go 1.16:

├── Make.dist
├── README.vendor
├── all.bash*
├── all.bat
├── all.rc*
├── bootstrap.bash*
├── buildall.bash*
├── clean.bash*
├── clean.bat
├── clean.rc*
├── cmd/
├── cmp.bash
├── go.mod
	├── go.sum
├── internal/
├── make.bash*
├── make.bat
├── make.rc*
├── race.bash*
├── race.bat
├── run.bash*
├── run.bat
├── run.rc*
├── testdata/
...
└── vendor/

1. Diseño estándar mínimo de la estructura del proyecto Go.

Con respecto a cómo se ve el diseño estándar de la estructura del proyecto de la aplicación Go, el equipo oficial de Go nunca ha proporcionado un estándar de referencia. Sin embargo, como líder técnico del proyecto de lenguaje Go, Russ Cox dio su opinión sobre el diseño estándar mínimo de la estructura del proyecto Go en una edición de un proyecto de código abierto. Él cree que el diseño estándar mínimo de los proyectos Go debería ser así.

// 在Go项目仓库根路径下
- go.mod
- LICENSE
- xx.go
- yy.go
...- go.mod
- LICENSE
- package1
	- package1.go
- package2
	- package2.go
...

Directorios como pkg, cmd y docs no deberían formar parte de la estructura estándar de los proyectos Go, al menos no deberían ser obligatorios.
El autor cree que el diseño estándar mínimo dado por Russ Cox está en línea con la filosofía "simple" que Go siempre ha defendido: este diseño es muy flexible y puede satisfacer las necesidades de varios proyectos de Go.

Sin embargo, antes de que Russ Cox elaborara los estándares mínimos anteriores, la comunidad Go se encontraba en realidad en un estado "sin estándares". El diseño estructural de los primeros proyectos del lenguaje Go todavía tenía un impacto en una gran cantidad de proyectos de código abierto Go existentes. Para algunos proyectos Go más grandes Para proyectos de aplicaciones, estamos obligados a expandirnos sobre la base del "diseño estándar mínimo" mencionado anteriormente. Obviamente, este tipo de expansión no será ciega, pero aún se referirá al diseño estructural del proyecto del lenguaje Go en sí, por lo que existe el siguiente diseño estructural recomendado estándar no oficial.

2. Ir a la estructura del proyecto con el fin de crear archivos ejecutables binarios.

Con base en la estructura inicial y la evolución posterior del proyecto de lenguaje Go en sí, la comunidad Go ha formado gradualmente una estructura de proyecto típica después de años de acumulación de práctica del lenguaje Go. Esta estructura es compatible con el diseño estándar mínimo de Russ Cox, como se muestra a continuación. cifra:

Insertar descripción de la imagen aquí
La figura anterior muestra la estructura de un proyecto típico de Go que admite la creación de archivos ejecutables binarios (en cmd). Echemos un vistazo a los usos de cada directorio importante.

directorio cmd : almacena el archivo fuente del paquete principal correspondiente al archivo ejecutable que creará el proyecto. Si es necesario crear varios archivos ejecutables, coloque el paquete principal de cada archivo ejecutable en un subdirectorio separado, como app1 y app2 en la figura. El paquete principal de cada aplicación en el directorio cmd conecta las dependencias de todo el proyecto y, en términos generales, el paquete principal debe ser muy conciso. Haremos algunos análisis de parámetros de línea de comando, inicialización de recursos, inicialización de instalaciones de registro, inicialización de conexión de base de datos, etc. en el paquete principal, y luego transferiremos el permiso de ejecución del programa a un objeto de control de ejecución de nivel superior. Algunos proyectos de Go han cambiado el nombre de cmd a aplicación, pero su función no ha cambiado.

directorio pkg : almacena los archivos de biblioteca que utiliza el propio proyecto y de los que depende el paquete principal del archivo ejecutable. Los proyectos externos pueden hacer referencia a los paquetes de este directorio y se consideran una agregación de paquetes de exportación de proyectos. Algunos proyectos cambian el nombre pkg a lib, pero el propósito del directorio permanece sin cambios. Dado que el proyecto de lenguaje Go en sí eliminó el directorio pkg en la versión 1.4, algunos proyectos colocan directamente los paquetes en la ruta raíz del proyecto, pero creo que para algunos proyectos más grandes, demasiados paquetes harán que el proyecto no tenga un directorio de nivel superior. Ya no es conciso y parece muy lleno, por lo que personalmente recomiendo mantener el directorio pkg para proyectos complejos de Go.

Makefile : Aquí el Makefile es el "representante" del script utilizado por la herramienta de compilación del proyecto. Puede representar el script utilizado por cualquier herramienta de compilación de terceros. Go no tiene herramientas de creación de proyectos integradas como make y bazel. Para algunos proyectos a mayor escala, las herramientas de creación de proyectos parecen ser indispensables. En los proyectos típicos de Go, los scripts de las herramientas de compilación del proyecto generalmente se colocan en el directorio de nivel superior del proyecto, como el Makefile aquí; para proyectos con muchos scripts de compilación, también puede crear un directorio de compilación y agregar el atributo de regla. archivos y scripts de subcompilación de los scripts de compilación. Póngalo en.

go.mod y go.sum : archivos de configuración utilizados para la gestión de dependencias del paquete de idioma Go. Similar al archivo pom.xml en el proyecto java . La versión 1.11 de Go introdujo el mecanismo del módulo Go. En la versión 1.16 de Go, el módulo Go se convirtió en el mecanismo predeterminado de construcción y gestión de paquetes de dependencia. Por lo tanto, para nuevos proyectos de Go, se recomienda gestionar las dependencias de paquetes basadas en módulos de Go. Para proyectos que no usan el módulo Go para la administración de paquetes (probablemente principalmente algunos proyectos de Go que usan versiones anteriores a Go 1.11), puede reemplazarlo con Gopkg.toml y Gopkg.lock de dep, o glide.yaml y glide.lock de glide, etc. .

● directorio de proveedores (opcional): proveedor es un mecanismo introducido en Go 1.5 para almacenar en caché versiones específicas de paquetes de dependencia localmente en el proyecto. Antes de que se introdujera el mecanismo del módulo Go, se podían lograr compilaciones reproducibles según el proveedor, lo que garantizaba que los programas ejecutables creados con el mismo código fuente fueran equivalentes. El módulo Go en sí puede lograr compilaciones reproducibles sin la necesidad de un proveedor. Por supuesto, el mecanismo del módulo Go también conserva el directorio del proveedor (go mod seller se puede usar para generar paquetes de dependencia bajo el proveedor; go build -mod=vendor se puede
usar para implementar compilación basada en proveedores ), por lo que el directorio de proveedores se considera un directorio opcional aquí. Generalmente, solo mantenemos el directorio de proveedores en el directorio raíz del proyecto; de lo contrario, causará una complejidad innecesaria en la selección de dependencias.

El módulo introducido en Go 1.11 es una colección de paquetes que pertenecen a la misma unidad de gestión de versiones. Go admite múltiples módulos en un proyecto/repositorio, pero este método de gestión puede introducir más complejidad que una cierta proporción de duplicación de código. Por lo tanto, si hay "desacuerdos" en la gestión de versiones en la estructura del proyecto, por ejemplo, las versiones de lanzamiento de app1 y app2 no siempre están sincronizadas, entonces el autor recomienda dividir el proyecto en varios proyectos (almacenes) y cada proyecto como un módulo
separado Realizar gestión y evolución de versiones .

3. Ir a la estructura del proyecto con el fin de construir solo bibliotecas.

Cuando se lanzó Go 1.4, el proyecto de lenguaje Go eliminó el directorio pkg en src. Este cambio estructural tiene un cierto impacto en la estructura de los proyectos de tipo biblioteca Go que solo crean bibliotecas. Echemos un vistazo al diseño estructural de un proyecto típico de tipo biblioteca de lenguaje Go, como se muestra en la siguiente figura:

Insertar descripción de la imagen aquí
Vemos que la estructura del proyecto de tipo biblioteca también es compatible con el diseño estándar mínimo de los proyectos de Go, pero es más simple que los proyectos de Go con el fin de crear ejecutables binarios.

● Se eliminaron los subdirectorios cmd y pkg: dado que solo estamos creando la biblioteca, no es necesario mantener el directorio cmd que almacena el archivo fuente del paquete principal del archivo binario; ya que la intención original de los proyectos de la biblioteca Go generalmente es exponer las API al externo (código abierto o divulgación interna dentro de la organización), por lo tanto, no es necesario agregarlo por separado en el directorio pkg.

● Proveedor ya no es un directorio opcional: para proyectos de tipo biblioteca, no se recomienda colocar el directorio de proveedor en el proyecto para almacenar en caché las dependencias de terceros de la biblioteca misma. Los proyectos de biblioteca solo pueden usar go.mod (o el directorio archivo de otras herramientas de gestión de dependencia de paquetes)) indique claramente los módulos o paquetes de los que depende el proyecto y los requisitos de versión.

4. Sobre el directorio interno

No importa qué tipo de proyecto Go sea, para los paquetes que no quieren estar expuestos a referencias externas y solo se usan dentro del proyecto, la estructura del proyecto se puede implementar a través del mecanismo de paquete interno introducido en la versión Go 1.4
.

Tomando el proyecto de la biblioteca como ejemplo, la forma más sencilla es agregar un directorio interno en el nivel superior y colocar todos los paquetes que no quieran estar expuestos al mundo exterior en este directorio, como ilib1 e ilib2 en la siguiente estructura del proyecto. :

// 带internal的Go库项目结构
$tree -F ./chapter2/sources/GoLibProj
GoLibProj
├── LICENSE
├── Makefile
├── README.md
├── go.mod
├── internal/
│ ├── ilib1/
│ └── ilib2/
├── lib.go
├── lib1/
│ └── lib1.go
└── lib2/
└── lib2.go

De esta manera, de acuerdo con el principio de funcionamiento del mecanismo interno de Go, ilib1 e ilib2 en el directorio interno se pueden importar y usar mediante código en otros directorios (como lib.go, lib1/lib1.go, etc.) con el Directorio GoLibProj como directorio raíz. Sin embargo, no puede ser utilizado por código fuera del directorio GoLibProj, lo que permite la exposición selectiva de los paquetes API .

Por lo tanto, después de comprender las estructuras del proyecto correspondientes a los diferentes tipos de proyectos, los desarrolladores pueden expandirse de acuerdo con las necesidades reales basándose en el núcleo de la estructura del proyecto anterior.

Supongo que te gusta

Origin blog.csdn.net/hai411741962/article/details/132673067
Recomendado
Clasificación