Proyectos modulares en Go usando paquetes privados 📦

22 de Junio del 2023 ¿Ves algún error? Corregir artículo golang-wallpaper

Mientras desarrollo, me he estado encontrando con problemas cada vez más recurrentes, y uno de ellos es la reutilización de módulos entre proyectos. Esto es algo que se puede aprovechar muy bien en Go, ya que es un lenguaje diseñado para trabajar de manera modular.

¿Qué es un paquete en Go?

En Go, un paquete es una forma de organizar y reutilizar código. Un paquete puede contener uno o más archivos fuente de Go y puede ser importado en otros programas de Go para usar sus funciones, variables y tipos exportados. Es un concepto fundamental en la programación de Go y ayuda a crear código modular y reutilizable.

Ventajas de usar paquetes privados

  1. Mayor seguridad: Los paquetes privados nos permiten proteger nuestro código fuente y evitar que sea accedido por personas no autorizadas.
  2. Mayor control: Al tener paquetes privados, podemos tener un mayor control sobre las dependencias de nuestro proyecto y asegurarnos de que se estén utilizando las versiones correctas.
  3. Mejora la reutilización de código: Los paquetes privados nos permiten compartir código entre proyectos de nuestra empresa de manera más eficiente, lo que puede mejorar la productividad y reducir el tiempo de desarrollo.
  4. Mayor escalabilidad: Con paquetes privados, podemos construir proyectos más grandes y complejos con mayor facilidad, ya que nos permite dividir nuestro código en módulos más pequeños y manejables.
  5. Mejora la calidad del código: Al tener paquetes privados, podemos asegurarnos de que nuestro código esté bien estructurado y siga las mejores prácticas de programación, lo que puede mejorar la calidad del código y reducir la cantidad de errores.
La clave para ser un buen programador es mantenerse en constante aprendizaje. 👉🏽

¿Cómo creamos un paquete privado en Go?

Para esto, plantearemos la siguiente situación:

Trabajamos en un equipo de más de 20 desarrolladores y nuestros proyectos necesitan una forma más homogénea de manejar los Logs, pero la naturaleza de nuestros proyectos nos obliga a ofuscar información sensible en nuestros Logs.

Este es un caso perfecto para aplicar el uso de paquetes privados. Podríamos proceder de la siguiente forma:

  1. Asignamos el proyecto del registro a un desarrollador específico (el que tenga más experiencia en el tema).

  2. El equipo de desarrolladores llega a un acuerdo para modelar la interfaz del Logger.

  3. Comienza la fase de desarrollo de nuestro proyecto de Logging. Ahora pondremos un ejemplo de cómo podría verse nuestro paquete de Go.

    internal

    obfuscator

    obfuscator.go

    logger

    logger.go

    .gitignore

    go.mod

    go.sum

    README.md

    Como pueden apreciar, nuestro paquete cuenta con dos subpaquetes: uno llamado Logger en la raíz del proyecto y otro llamado Obfuscator dentro de la carpeta Internal.

    Tip 💡: Todo el código dentro de la carpeta internal hace que sea imposible de importar. De esta manera, podemos mantener funcionalidades ocultas para la exportación en otros proyectos donde se usará el paquete.

  4. Ahora desarrollamos nuestros dos paquetes (lo haré lo más breve y simple posible ya que el enfoque de este artículo no es enseñarles a hacer un logger)

    ~
    package logger import ( "fmt" "private-packages-go/internal/obfuscator" ) type Logger interface { Debug(msg string) } type CompanyLogger struct { obfuscator *obfuscator.Obfuscator } func NewCompanyLogger() *CompanyLogger { o := obfuscator.NewObfuscator() return &CompanyLogger{ obfuscator: o, } } func (c *CompanyLogger) Debug(msg string) { nMsg := c.obfuscator.Obfuscate(msg) fmt.Println(nMsg) }

    Si pueden notar algo, es que el ofuscador se inicializa y asigna dentro del "constructor" del logger, y no se puede asignar desde el "constructor". Esto permite que nadie pueda cambiar la lógica de qué cosa se oculta o no.

    Si tu paquete necesita alguna otra parte de tu proyecto, como un ofuscador personalizado, lo ideal es pasar una interfaz en el constructor que los ofuscadores deban cumplir, en lugar de una implementación.

    En nuestro caso, el ofuscador será único y controlado por el paquete de Logging.

  5. Es hora de cargar nuestro paquete en un repositorio privado en GitHub y comenzar a usarlo en otros proyectos.

¿Cómo usamos paquetes privados en Go?

Para esto necesitamos tener configurado nuestra SSH Key de Github en nuestra computadora.

  1. Cambiarémos el URL de Git usando el siguiente comando:

    ~
    git config --global url.git@github.com:.insteadOf https://github.com/
  2. Para estar seguros revisarémos si la configuración se cambio de forma correcta.

    ~
    cat ~/.gitconfig
     $ [url "git@github.com:"] $  insteadOf = https://github.com/
  3. Agregamos el módulo en la variable GOPRIVATE.

    ~
    export GOPRIVATE=github.com/private/repo
  4. Ahora simplemente usamos la herramienta get de Go para traer el paquete a nuestro proyecto.

    ~
    go get github.com/private/repo
  5. Momento de usar nuestro paquete de Go.

    ~
    package main import "github.com/solrac97gr/private-packages-go/logger" type Service struct { logger logger.Logger } func NewService(l logger.Logger) *Service { return &Service{ logger: l, } } func (s *Service) DoSomething() { msg := "I am secret 🤫, I am not a secret 😎" s.logger.Debug(msg) } func main() { lggr := logger.NewCompanyLogger() srv := NewService(lggr) srv.DoSomething() }
     $ I am not a secret 😎

    Podemos notar que estamos usando la interfaz y no la implementación, lo que nos permitirá usar mocks en el futuro para mejorar las pruebas. Además, debemos considerar que los paquetes deben tener sus propias pruebas, lo cual no es opcional.

Conclusión

En conclusión, la reutilización de módulos entre proyectos es un problema común en el desarrollo de software, pero en Go, este problema puede ser abordado de manera efectiva gracias a su diseño modular. Al aprovechar los paquetes privados, podemos compartir código de manera más eficiente y mejorar la reutilización de módulos entre proyectos. De esta manera, podemos mejorar la productividad y reducir el tiempo de desarrollo en nuestra empresa.

Conviértete en un Go Ninja 🥷.Suscríbete a mi newsletter y recibe las últimas novedades en Go.