Hace unos días comence a crear un proyecto en Go que requería de muchos archivos, entonces comencé a buscar información sobre cual es la estructura correcta de un proyecto en Go, logré obtener cierta información que era buena pero no me convencia, por ende decidí crear este Post y compartirlo con los desarrolladores que se inician en el Lenguaje de Programación Go. En este Post te compartiré Cual Es la Estructura Correcta de un Proyecto en Go, vamos con ello.
Antes de continuar te invito a leer los siguiente artículos:
- Que es Go y otros Detalles
- Trabajando con Strings en Go
- Buenas Prácticas para Crear Interfaces Limpias en Go
- Como Crear una Página Web con Go 1.15 y Bootstrap 4.5 – Parte1,
- Características que hacen Agradable al Lenguaje de Programación Go
- Como usar el Lenguaje de Programación Go + Primera aplicación Hola Mundo
- Tipos de Variables en el Lenguaje de Programación Go
- Como Recorrer un Array en Go
- Puedes leer más Posts en la categoría Go
Asimismo, te invito a escuchar el Podcast: “Si No Tienes Experiencia Para Un Puesto De Trabajo, Créala !” y “¿ Qué Es NoCode Development ?” (Anchor Podcast):
Spotify: | Sound Cloud: | Apple Podcasts | Anchor Podcasts |
Bien ahora continuemos con el Post: Cual Es la Estructura Correcta de un Proyecto en Go.
Cual Es la Estructura Correcta de un Proyecto en Go
A continuación te compartiré una estructura estándar, basada en un conjunto de patrones de diseño de proyectos emergentes y con experiencia. Tiene una serie de pequeñas mejoras junto con varios directorios de soporte comunes a cualquier aplicación del mundo real lo suficientemente grande.
En la imagen anterior puedes ver que hay algunos archivos de GitHub como .gitignore y README.md, el resto de archivos son parte de la estructura estándar de Go.
Te preguntarás, que archivos van en cada uno de los directorios de la estructura anterior, veamos ello a continuación (colocaré algunos ejemplos de proyectos con Go alojados en GitHub).
/api
En este directorio puedes colocar especificaciones OpenAPI/Swagger, archivos de esquema JSON, archivos de definición de protocolo.
Ejemplos:
- https://github.com/kubernetes/kubernetes/tree/master/api
- https://github.com/moby/moby/tree/master/api
/assets
En este directorio puedes colocar archivos como imágenes, logotipos, hojas de estilo css, archivos JavaScript, etc.
/build
Este directorio es de empaque e integración continua. Puedes colocar tu nube (AMI), contenedor (Docker), OS (deb, rpm, pkg) configuraciones de paquete y secuencias de comandos dentro de el directorio /build/package
También puedes colocar tus configuraciones y scripts de CI (travis, circle, drone) en el directorio /build/ci. Ten en cuenta que algunas de las herramientas de CI (p. ej., Travis CI) son muy exigentes con la ubicación de sus archivos de configuración. Intenta poner los archivos de configuración en el directorio /build/ci vinculándolos a la ubicación donde las herramientas de CI los esperan cuando sea posible (no te preocupes si no es así y si mantener esos archivos en el directorio raíz te facilita la vida.
Ejemplo:
/cmd
El nombre del directorio de cada aplicación debe coincidir con el nombre del ejecutable que deseas tener (p. ej., /cmd/miapp). No pongas mucho código en el directorio de la aplicación. Si crees que el código se puede importar y usar en otros proyectos, entonces debería estar en el directorio /pkg. Si el código no es reutilizable o si no deseas que otros lo reutilicen, coloca ese código en el directorio /internal.
Ejemplos:
- https://github.com/vmware-tanzu/velero/tree/main/cmd (solo una función muy pequeña main con todo lo demás en paquetes)
- https://github.com/moby/moby/tree/master/cmd
- https://github.com/prometheus/prometheus/tree/main/cmd
- https://github.com/influxdata/influxdb/tree/master/cmd
- https://github.com/kubernetes/kubernetes/tree/master/cmd
- https://github.com/dapr/dapr/tree/master/cmd
- https://github.com/ethereum/go-ethereum/tree/master/cmd
/configs
En este directorio puedes colocar plantillas de archivos de configuración o configuraciones predeterminadas, como confd o consul-template
/deployments
Este directorio esta enfocado en IaaS, PaaS, configuraciones y plantillas de implementación de orquestación de sistemas y contenedores (docker-compose, kubernetes/helm, mesos, terraform, bosh).
/docs
Este directorio es para los documentos del usuario (además de la documentación generada por tu godoc).
Ejemplos:
- https://github.com/gohugoio/hugo/tree/master/docs
- https://github.com/openshift/origin/tree/master/docs
- https://github.com/dapr/dapr/tree/master/docs
/examples
Acá puedes colocar ejemplos para tus aplicaciones y/o librerías públicas.
Ejemplos:
- https://github.com/nats-io/nats.go/tree/master/examples
- https://github.com/docker-slim/docker-slim/tree/master/examples
- https://github.com/hashicorp/packer/tree/master/ejemplos
/githooks
Aca puedes colocar tus ganchos o hoohks de GitHub.
/init
Aca puedes colocar las configuraciones de inicio del sistema (systemd, upstart, sysv) y administrador/supervisor de procesos (runit, supervisord).
/internal
Acá va el código que no deseas que otros importen en sus aplicaciones o librerías. Ten en cuenta que este patrón de diseño lo impone el propio compilador de Go. Consulta las notas de lanzamiento de Go 1.4 para obtener más detalles. Asimismo ten en cuenta que no está limitado al directorio de nivel superior internal. Puedes tener más de un directorio internal en cualquier nivel de la estructura de tu proyecto.
Ejemplos:
- https://github.com/hashicorp/terraform/tree/main/internal
- https://github.com/influxdata/influxdb/tree/master/internal
- https://github.com/perkeep/perkeep/tree/master/internal
- https://github.com/jaegertracing/jaeger/tree/main/internal
- https://github.com/moby/moby/tree/master/internal
- https://github.com/satellity/satellity/tree/main/internal
Ejemplo (internal/pkg):
/pkg
Acá puedes colocar código de librerías que está bien para usar en aplicaciones externas (p. ej., /pkg/milibreriapublica). Otros proyectos importarán estas bibliotecas esperando que funcionen, así que piénsalo dos veces antes de poner algo aquí. Ten en cuenta que el directorio internal es una mejor manera de asegurarse que tus paquetes privados no se puedan importar porque Go lo impone. El directorio /pkg sigue siendo una buena manera de comunicar explícitamente que el código en ese directorio es seguro para que lo usen otros.
También es una forma de agrupar el código de Go en un solo lugar cuando tu directorio raíz contiene muchos componentes y directorios que no son de Go, lo que facilita la ejecución de varias herramientas de Go.
Ten en cuenta que este no es un patrón universalmente aceptado y por cada repositorio popular que lo usa, puedes encontrar 10 que no lo hacen. Depende de ti decidir si quieres usar este patrón o no. Independientemente de si es o no un buen patrón, más personas sabrán lo que quieres decir. Puede ser un poco confuso para algunos de los nuevos desarrolladores de Go, pero es una confusión bastante simple de resolver y ese es uno de los objetivos de este repositorio de diseño de proyecto.
No lo uses si tu proyecto es realmente pequeño y donde un nivel adicional de anidamiento no agrega mucho valor (a menos que realmente lo desees). Piénsalo cuando sea lo suficientemente grande y tu directorio raíz esté bastante ocupado (especialmente si tienes muchos componentes de la aplicación que no son de Go).
Los orígenes del directorio pkg: el antiguo código fuente de Go que usaba pkg para sus paquetes y luego varios proyectos de Go en la comunidad comenzaron a copiar el patrón.
Ejemplos:
- https://github.com/jaegertracing/jaeger/tree/master/pkg
- https://github.com/istio/istio/tree/master/pkg
- https://github.com/GoogleContainerTools/kaniko/tree/master/pkg
- https://github.com/google/gvisor/tree/master/pkg
- https://github.com/google/syzkaller/tree/master/pkg
/scripts
Acá puedes colocar scripts para realizar varias operaciones de compilación, instalación, análisis, etc. Estos scripts mantienen el Makefile de nivel raíz pequeño y simple.
Ejemplos:
- https://github.com/kubernetes/helm/tree/master/scripts
- https://github.com/cockroachdb/cockroach/tree/master/scripts
- https://github.com/hashicorp/terraform/tree/master/scripts
/test
Acá puedes colocar aplicaciones de prueba externas adicionales y datos de prueba. Siéntete libre de estructurar el directorio /test como quieras. Para proyectos más grandes, tiene sentido tener un subdirectorio de datos. Por ejemplo, puede tener /test/data o /test/testdata si necesitas ignorar lo que hay en esos directorios. Ten en cuenta que Go también ignorará los directorios o archivos que comiencen con “.” o “_”, por lo que tiene más flexibilidad en términos de cómo nombrar tu directorio de datos de prueba.
Ejemplo:
- https://github.com/openshift/origin/tree/master/test (los datos de prueba están en el subdirectorio /testdata)
/third_party
Acá puedes colocar las herramientas auxiliares externas, código bifurcado y otras utilidades de terceros (p. ej., interfaz de usuario de Swagger).
/tools
Acá puedes colocar las herramientas de apoyo para tu proyecto. Ten en cuenta que estas herramientas pueden importar código de los directorios /pkg e /internal.
/vendor
Aca van las dependencias de tu aplicación (administradas manualmente o por tu herramienta de administración de dependencias favorita, como la nueva función integrada modules, pero hasta la fecha de este Post, aún experimental).
No comprometas las dependencias de tu aplicación si estás creando una librería. Ten en cuenta que dado que Go 1.13 también habilitó la función de proxy del módulo (utilizando https://proxy.golang.orgc omo su servidor proxy de módulo de forma predeterminada). Lea más al respecto aquí para ver si se ajusta a todos tus requisitos y limitaciones. Si es así, entonces no necesitarás el directorio vendor en absoluto.
/web
Acá van los componentes específicos de una aplicación web: assets web estáticos, plantillas del lado del servidor y SPA.
/website
Este es el lugar para colocar los datos del sitio web de tu proyecto si no estás utilizando las páginas de GitHub.
Ejemplos:
- https://github.com/hashicorp/vault/tree/master/website
- https://github.com/perkeep/perkeep/tree/master/website
Espero que te sirva de mucho este Post y puedas mantener bien estructurados y ordenados tus proyectos con Go.
Conclusión
En este Post has aprendido a como estructurar un proyecto con el Lenguaje de Programación Go. La mejor forma de dominar esta organización, es aplicándola a tus proyectos.
Nota(s)
- No olvides que debemos usar la Tecnología para hacer cosas Buenas por el Mundo.
Síguenos en las Redes Sociales para que no te pierdas nuestros próximos contenidos.