Cómo usar una ruta de import diferente al publicar un paquete en Go

Go es un lenguaje de programación cuyas bibliotecas e imports se resuelven en base a namespaces que simulan ser URLs, como en los paquetes más profesionales de Java. La mayoría de elementos de la biblioteca estandar se importan desde ubicaciones cortas como "log" o "net/http", lo cual es fácil de recordar, pero para paquetes extra, a menudo los imports se hacen desde rutas cualificadas como "github.com/spf13/cobra" o "golang.org/x/crypto".

Este tipo de sistema de rutas cualificadas por un lado facilita el evitar conflictos en los espacios de nombres, de la misma forma que Java lo conseguía. Una organización puede publicar sus paquetes bajo "empresa.corp/domains/users" o "empresa.corp/domains/customers", y en condiciones normales no debería haber conflicto debido a que lleva el propio nombre cualificado de la empresa como prefijo de sus paquetes. Sin embargo, también es cierto que cuando se usan forjas de terceros como GitHub o SourceHut, las rutas de import acaban teniendo una forma poco protocolaria como "github.com/google/subcommands".

Una forma de solucionar este problema puede ser la idea de utilizar un dominio si posees uno. Por ejemplo, me gustaría importar mis paquetes desde "danirod.es/pkg/foo", en vez de otra ruta como "github.com/danirod/foo", "gitlab.com/danirod/foo" o "git.danirod.es/danirod/foo". Pero claro, cuando hagamos el go get o el go install, tratará de ir a esa URL para obtener el paquete. ¿Cómo se puede resolver esto?

Por suerte, el sistema que usa Go para descargar paquetes de internet ante una sentencia de import no reconocida está documentado en su página web. Aquí se nos habla de que Go reconoce automáticamente imports de forjas como GitHub o BitBucket. También se indica que si se pone una ruta de import que termina con un sufijo como .git o como .hg, lo reconocerá y tratará de utilizar ese sistema de control de versiones para hacer el import. Pero lo importante se cuenta un poco más abajo: la resolución mediante HTTP.

Esencialmente, ante un import que no pueda resolver Go, tirará una petición HTTPS a la ruta del import, añadiendo el queryparam ?go-get=1. Buscará una etiqueta <meta> que tenga el siguiente formato:

<meta name="go-import" content="import-prefix vcs repo-root">

Donde import-prefix es la raíz del paquete (ahora explico), vcs es un string que indica el tipo de control de versiones que tiene que usar Go para descargar el paquete (por ejemplo, "git" o "svn"), y repo-root es la URL al repositorio desde el que clonar el paquete.

En otras palabras, si quiero configurar mi paquete para que se pueda importar como import "danirod.es/pkg/foo", tendré que asegurarme de que cuando se visita https://danirod.es/pkg/foo?go-get=1, en la parte superior de la página se incluye una metaetiqueta que tenga el siguiente formato:

<meta name="go-import" content="danirod.es/pkg/foo git https://github.com/danirod/foo">

Esto es lo que le permite a Go saber que para obtener el paquete danirod.es/pkg/foo tiene que hacer git clone https://github.com/danirod/foo.

Sobre la cuestión del import-prefix, su principal propósito es indicar cuál es la raíz real del proyecto. Esto es importante si se trata de resolver un import de un subpaquete concreto, como pueda ser golang.org/x/crypto/argon2. En ese caso, Go tratará de descargar el paquete inicialmente desde https://golang.org/x/crypto/argon2?go-get=1, por lo que especificar como import-root el nombre golang.org/x/cyrpto, puede señalizarle a GO que realmente este paquete no es independiente, sino que pertenece a otro.

Fecha de publicación:

Etiquetado en:

Avatar de Dani

Sobre

Ver el resto de posts »