Información sobre los paquetes

Completado

Los paquetes en Go son como bibliotecas o módulos en otros lenguajes de programación. Puede empaquetar el código y reutilizarlo en otra parte. El código fuente de un paquete se puede distribuir en más de un archivo .go. Hasta ahora, hemos escrito el paquete main y hemos hecho algunas referencias a otros paquetes nativos.

En esta sección, aprenderá qué es un paquete. También obtendrá información sobre cómo crear uno y cómo consumir paquetes externos.

Paquete principal

Como habrá observado, incluso el programa más sencillo de Go debe formar parte de un paquete. Normalmente, el paquete predeterminado es el paquete main, el que hemos usado hasta ahora. Si un programa forma parte del paquete main, Go genera un archivo binario. Cuando se ejecuta ese archivo, se llama a la función main().

En otras palabras, cuando se usa el paquete main, el programa genera un archivo ejecutable independiente. Pero cuando un programa forma parte de un paquete que no es main, Go no genera un archivo binario, Genera un archivo de almacenamiento de paquetes (un archivo que tiene la extensión .a).

En Go, los nombres de paquetes siguen una convención. Un paquete usa la última parte de su ruta de acceso de importación como nombre. Por ejemplo, la biblioteca estándar de Go contiene un paquete denominado math/cmplx, que proporciona código útil para trabajar con números complejos. La ruta de acceso de importación de este paquete es math/cmplx y se importa de la siguiente forma:

import "math/cmplx"

Para hacer referencia a los objetos del paquete, use el nombre del paquete, cmplx, de la siguiente forma:

cmplx.Inf()

Vamos a crear un paquete.

Creación de un paquete

Cree un nuevo directorio llamado calculator en el directorio $GOPATH/src. Cree un archivo llamado sum.go. El árbol del directorio debe ser similar al siguiente:

src/
  calculator/
    sum.go

Inicialice el archivo sum.go con el nombre del paquete:

package calculator

Ahora puede empezar a escribir las funciones y las variables del paquete. A diferencia de otros lenguajes de programación, Go no proporciona las palabras clave public o private para indicar si se puede llamar a una variable o a una función desde fuera o dentro del paquete. Pero Go sigue dos reglas simples:

  • Si quiere que algo sea privado, escriba su nombre con la primera letra en minúscula.
  • Si quiere que algo sea público, escriba su nombre con la primera letra en mayúscula.

Vamos a agregar el siguiente código al paquete "calculator" que estamos creando:

package calculator

var logMessage = "[LOG]"

// Version of the calculator
var Version = "1.0"

func internalSum(number int) int {
    return number - 1
}

// Sum two integer numbers
func Sum(number1, number2 int) int {
    return number1 + number2
}

Vamos a fijarnos en algunas cosas de este código:

  • Solo se puede llamar a la variable logMessage desde dentro del paquete.
  • Se puede acceder a la variable Version desde cualquier lugar. Se recomienda incluir un comentario para describir el propósito de la variable. Esta descripción es útil para cualquier persona que use el paquete.
  • Solo se puede llamar a la función internalSum desde dentro del paquete.
  • Se puede acceder a la función Sum desde cualquier lugar. Se recomienda incluir un comentario para describir el propósito de la función.

Para confirmar que todo funciona, puede ejecutar el comando go build en el directorio calculator. Si lo hace, observe que no se genera ningún archivo binario ejecutable.

Creación de un módulo

Ha agrupado la funcionalidad de "calculator" en un paquete. Ahora es el momento de agrupar el paquete en un módulo. Los módulos de Go normalmente contienen paquetes que ofrecen funcionalidad relacionada. El módulo del paquete especifica el contexto que necesita Go para ejecutar el código que ha agrupado. Esta información contextual incluye la versión de Go para la que se ha escrito el código.

Además, los módulos ayudan a otros desarrolladores a hacer referencia a versiones específicas del código y facilitan el trabajo con dependencias. Otra ventaja es que el código fuente del programa no tiene que existir estrictamente en el directorio $GOPATH/src. Sin esta restricción, resulta más cómodo trabajar con diferentes versiones de paquetes en otros proyectos al mismo tiempo.

Por tanto, para crear un módulo para el paquete calculator, ejecute el siguiente comando en el directorio raíz ($GOPATH/src/calculator):

go mod init github.com/myuser/calculator

Después de ejecutar este comando, github.com/myuser/calculator se convierte en el nombre del módulo. Usará ese nombre para hacer referencia al paquete en otros programas. El comando también crea un nuevo archivo denominado go.mod. Por último, el árbol del directorio ahora debería similar a este:

src/
  calculator/
    go.mod
    sum.go

Por otro lado, el contenido del archivo go.mod debería ser similar al siguiente código (aunque la versión de Go podría ser diferente):

module github.com/myuser/calculator

go 1.14

Para hacer referencia al paquete calculator en otros programas, debe importarlo usando el nombre del módulo. En este caso, su nombre es github.com/myuser/calculator. Veamos ahora un ejemplo de cómo usar este paquete.

Nota:

Históricamente, la administración de dependencias en Go nunca ha sido fácil. El sistema de administración de dependencias sigue siendo un trabajo en curso. Si quiere obtener más información sobre los módulos, consulte esta serie de publicaciones en el blog de Go.

Referencia a un paquete local (un módulo)

Ahora vamos a usar el paquete. Continuaremos con la aplicación de ejemplo que hemos usado hasta ahora. Esta vez, en lugar de tener la función sum en el paquete main, vamos a usar la función que hemos creado anteriormente en el paquete calculator.

La estructura de árbol del archivo ahora debería ser similar a la siguiente:

src/
  calculator/
    go.mod
    sum.go
  helloworld/
    main.go

Usaremos este código para el archivo $GOPATH/src/helloworld/main.go:

package main

import (
  "fmt"
  "github.com/myuser/calculator"
)

func main() {
    total := calculator.Sum(3, 5)
    fmt.Println(total)
    fmt.Println("Version: ", calculator.Version)
}

Observe que la instrucción "import" usa el nombre del paquete que ha creado: calculator. Para llamar a la función Sum desde ese paquete, debe incluir el nombre del paquete como calculator.Sum. Por último, ahora también tiene acceso a la variable Version. Puede llamar a la variable de esta forma: calculator.Version.

Si intenta ejecutar el programa ahora, no funcionará. Debe indicarle a Go que está usando módulos para hacer referencia a otros paquetes. Para ello, ejecute este comando en el directorio $GOPATH/src/helloworld:

go mod init helloworld

En el comando anterior, helloworld es el nombre del proyecto. Este comando crea un nuevo archivo go.mod, por lo que ahora el árbol del directorio tiene el siguiente aspecto:

src/
  calculator/
    go.mod
    sum.go
  helloworld/
    go.mod
    main.go

Al abrir el archivo go.mod, debería ver algo parecido al siguiente código (aunque la versión de Go podría ser diferente):

module helloworld

go 1.14

Como está haciendo referencia a una copia local del módulo, debe informar a Go de que no quiere usar una ubicación remota. De este modo, debe modificar manualmente el archivo go.mod para que incluya la referencia, tal y como se muestra a continuación:

module helloworld

go 1.14

require github.com/myuser/calculator v0.0.0

replace github.com/myuser/calculator => ../calculator

La palabra clave replace especifica el uso de un directorio local en lugar de una ubicación remota para el módulo. En este caso, los programas helloworld y calculator se encuentran en $GOPATH/src, por lo que la ubicación es simplemente ../calculator. Si el origen del módulo se encontrara en una ubicación diferente, definiría la ruta de acceso local aquí.

Ejecute el programa mediante este comando:

go run main.go

La salida debería ser similar a la siguiente:

8
Version:  1.0

Desafío 1

¿Qué ocurre si intenta llamar a la variable logMessage o a la función internalSum del paquete calculator en la aplicación principal? ¿Funciona? Pruébalo

Solución del desafío:

package main

import (
 "fmt"
 "github.com/myuser/calculator"
)

func main() {
    total := calculator.internalSum(5)
    fmt.Println(total)
    fmt.Println("Version: ", calculator.logMessage)
}

Publicación de un paquete

Publicar un paquete de Go es bastante sencillo. Solo tiene que hacer que el código fuente del paquete esté disponible públicamente. La mayoría de los desarrolladores usan GitHub para que los paquetes estén disponibles para el público, por lo que a veces encontrará referencias a github.com en instrucciones de importación.

Por ejemplo, si quiere publicar el paquete calculator en su cuenta de GitHub, debe crear un repositorio denominado calculator. La dirección URL debería tener un aspecto similar al siguiente:

https://github.com/myuser/calculator

Tendrá que crear una versión de los paquetes etiquetando el repositorio de la siguiente manera:

git tag v0.1.0
git push origin v0.1.0

Los desarrolladores que quieran usar el paquete (incluido usted) harán referencia a él de esta forma:

import "github.com/myuser/calculator"

Vamos a profundizar más en cómo hacer referencia a paquetes de terceros.

Referencia a paquetes externos (de terceros)

A veces, los programas necesitan hacer referencia a paquetes escritos por otros desarrolladores. Normalmente, esos paquetes están disponibles en GitHub. Las siguientes instrucciones para hacer referencia a paquetes de terceros funcionan tanto si va a desarrollar un paquete (uno distinto de main) como un programa independiente (el paquete main).

Vamos a agregar una referencia al paquete rsc.io/quote:

package main

import (
    "fmt"
    "github.com/myuser/calculator"
    "rsc.io/quote"
)

func main() {
    total := calculator.Sum(3, 5)
    fmt.Println(total)
    fmt.Println("Version: ", calculator.Version)
    fmt.Println(quote.Hello())
}

Si usa Visual Studio Code, el archivo go.mod se actualiza al guardar el archivo. Ahora tiene esta apariencia:

module helloworld

go 1.14

require (
    github.com/myuser/calculator v0.0.0
    rsc.io/quote v1.5.2
)

replace github.com/myuser/calculator => ../calculator

Observe cómo rsc.io/quote hace referencia a una versión específica del paquete. Cuando necesite actualizar las dependencias de su programa, deberá cambiar la versión aquí.

Ejecute el programa de nuevo mediante este comando:

go run main.go

La salida debe ser similar a esta:

8
Version:  1.0
Hello, world.

Todas las referencias futuras a paquetes de terceros deberán incluirse en el archivo go.mod. Al ejecutar o compilar la aplicación, Go descargará todas sus dependencias.