Un paquete está compuesto por archivos de Go que se alojan en el mismo directorio y tienen la misma instrucción de paquetes al inicio. Puede incluir funcionalidad adicional de paquetes para hacer que tus programas sean más sofisticados. Algunos paquetes están disponibles a través de la biblioteca de Go Standard y, por lo tanto, se incluyen con su instalación de Go. Otros se pueden instalar con el comando go get de Go. También puede crear sus propios paquetes de Go creando archivos de Go en el mismo directorio en el que desee compartir el código, con la instrucción de paquete necesaria.

A través de este tutorial, podrás escribir paquetes Go para utilizarlos en otros archivos de programación.

Requisitos previos

  • Configurar un entorno de programación de Go siguiendo uno de los tutoriales de la serie Cómo instalar y configurar un entorno de programación local para Go. Cree su espacio de trabajo Go siguiendo el paso 5 en los tutoriales de entorno de programación local. Para seguir el ejemplo y las convenciones de nomenclatura de este artículo, lea la primera sección: Escribir e importar de paquetes.
  • Para ampliar su conocimiento de GOPATH, lea nuestro artículo Información sobre GOPATH.

Escribir e importar paquetes

Escribir un paquete es como escribir cualquier archivo de Go. Los paquetes pueden contener definiciones de funciones, tipos y variables que luego pueden utilizarse en otros programas de Go.

Para crear un nuevo paquete, es necesario encontrarse en el espacio de trabajo de Go propio. Normalmente, esto se encuentra en gopath. Por ejemplo, en este tutorial daremos el nombre greet al paquete. Para hacer esto, creamos un directorio llamado greet en nuestro gopath, en el espacio de nuestro proyecto. Si nuestra organización fuera gopherguides y quisiéramos crear el paquete greet con la organización mientras usamos Github como nuestro repositorio de código, nuestro directorio tendría el siguiente aspecto:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides

El directorio greet se necuentra dentro del directorio gopherguides:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                └── greet

Por último, podemos añadir el primer archivo en nuestro directorio. Se considera práctica frecuente que el archivo primary o entry point de un paquete lleve el nombre del directorio. En este caso, crearíamos un archivo llamado greet.go dentro del directorio greet:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                └── greet
                    └── greet.go

Con el archivo creado, podemos comenzar a escribir el código propio que queramos volver a usar o compartir en proyectos. En este caso, crearemos una función llamada Hello que imprima Hello World.

Abra su archivo greet.go en su editor de texto y añada el siguiente código:

greet.go
package greet

import "fmt"

func Hello() {
    fmt.Println("Hello, World!")
}

Desglosaremos este primer archivo. En la primera línea de cada archivo se necesita el nombre del package en el que trabaje. Debido a que se encuentra en el paquete greet, utiliza la palabra package seguida del nombre del paquete:

package greet

Esto indicará al compilador que considere todo en el archivo como parte del paquete greet.

Luego, declare cualquier otro paquete que deba usar con la instrucción import. Sólo usará uno en este archivo: fmt:

import "fmt"

Por último, cree la función Hello. Se usará el paquete fmt para imprimir Hello, World!:

func Hello() {
    fmt.Println("Hello, World!")
}

Ahora que escribió el paquete greet, puede utilizarlo en cualquier otro paquete que cree. Crearemos un nuevo paquete en el que usará su paquete greet.

Crearemos un paquete llamado example, lo cual significa que necesita un directorio llamado example. Cree este paquete en su organización gopherguides, para que la estructura de directorios tenga el siguiente aspecto:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                    └── example

Ahora que dispone del directorio para su nuevo paquete, puede crear el archivo de punto de entrada. Debido a que este será un programa ejecutable, es recomendable asignarle el nombre main.go:

└── $GOPATH
    └── src
        └── github.com
            └── gopherguides
                └── example
                    └── main.go

En su editor de texto, abra main.go y añada el siguiente código para invocar al paquete greet:

main.go
package main

import "github.com/gopherguides/greet"

func main() {
    greet.Hello()
}

Debido a que importará un paquete, debe invocar la función haciendo referencia al nombre del paquete en notación de punto. La notación de punto es la práctica de poner un punto . entre el nombre del paquete que usa y el recurso en ese paquete que quiere usar. Por ejemplo, en su paquete greet, tiene la función Hello como recurso. Si desea invocar ese recurso, debe utilizar la notación de punto de greet.Hello().

Ahora, podrá abrir su terminal y ejecutar el programa en la línea de comandos:

  • go run main.go

Cuando lo haga, verá el siguiente resultado:

Output
Hello, World!

Para ver cómo puede usar variables en un paquete, añadiremos una definición variable en su archivo greet.go:

greet.go
package greet

import "fmt"

var Shark = "Sammy"

func Hello() {
    fmt.Println("Hello, World!")
}

Luego, abra su archivo main.go y añada la siguiente línea resaltada para invocar a la variable de greet.go en una función fmt.Println():

main.go
package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)
}

Una vez que ejecute el programa de nuevo:

  • go run main.go

Obtendrá el siguiente resultado:

Output
Hello, World! Sammy

Por último, también definiremos un tipo en el archivo greet.go. Crearás el tipo Octopus con los campos name y color, y una función que imprimirá los campos cuando se invoque:

greet.go
package greet

import "fmt"

var Shark = "Sammy"

type Octopus struct {
    Name  string
    Color string
}

func (o Octopus) String() string {
    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}

func Hello() {
    fmt.Println("Hello, World!")
}

Abra main.go para crear una instancia de ese tipo al final del archivo:

main.go
package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)

    oct := greet.Octopus{
        Name:  "Jesse",
        Color: "orange",
    }

    fmt.Println(oct.String())
}

Una vez que haya creado una instancia de tipo Octupus con oct := greet.Octopus, podrá acceder a las funciones y los campos del tipo dentro del espacio de nombres del archivo main.go. Esto le permite escribir oct.String() en la última línea sin invocar a greet. También podrías invocar uno de los campos de tipo como oct.Color sin hacer referencia al nombre del paquete greet.

El método String del tipo Octopus utiliza la función fmt.Sprintf para crear una frase y muestra con returns el resultado, una cadena, al elemento de llamada (en este caso, su programa principal).

Cuando ejecute el programa, verá el siguiente resultado:

  • go run main.go
Output
Hello, World! Sammy The octopus's name is "Jesse" and is the color orange.

Al crear el método String en Octopus, accede a una alternativa reutilizable para imprimir información sobre su tipo personalizado. Si quiere cambiar el comportamiento de este método en el futuro, solo tiene que editarlo.

Código exportado

Posiblemente haya observado que todas las declaraciones del archivo de greet.go que invocó llevaban mayúsculas. Go no incluye, como otros lenguajes, el concepto de modificadores public, private o protected. La visibilidad externa se controla con mayúsculas. Los tipos, las variables, las funciones y otros elementos que empiezan con mayúsculas están disponibles de forma pública, fuera del paquete actual. Un símbolo visible fuera de su paquete se considera como exported.

Si añade un nuevo método a Octopus llamado reset, puede invocarlo desde el interior del paquete greet, pero no desde su archivo main.go, que se encuentra fuera del paquete greet:

greet.go
package greet

import "fmt"

var Shark = "Sammy"

type Octopus struct {
    Name  string
    Color string
}

func (o Octopus) String() string {
    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}

func (o *Octopus) reset() {
    o.Name = ""
    o.Color = ""
}

func Hello() {
    fmt.Println("Hello, World!")
}

Si intenta invocar reset desde el archivo main.go:

main.go
package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)

    oct := greet.Octopus{
        Name:  "Jesse",
        Color: "orange",
    }

    fmt.Println(oct.String())

    oct.reset()
}

Verá el siguiente error de compilación:

Output
oct.reset undefined (cannot refer to unexported field or method greet.Octopus.reset)

Para aplicar export a la funcionalidad reset desde Octopus, use la R mayúscula en reset:

greet.go
package greet

import "fmt"

var Shark = "Sammy"

type Octopus struct {
    Name  string
    Color string
}

func (o Octopus) String() string {
    return fmt.Sprintf("The octopus's name is %q and is the color %s.", o.Name, o.Color)
}

func (o *Octopus) Reset() {
    o.Name = ""
    o.Color = ""
}

func Hello() {
    fmt.Println("Hello, World!")
}

Como resultado, puede invocar a Reset desde su otro paquete sin obtener un error:

main.go
package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)

    oct := greet.Octopus{
        Name:  "Jesse",
        Color: "orange",
    }

    fmt.Println(oct.String())

    oct.Reset()

    fmt.Println(oct.String())
}

Ahora, si ejecuta el programa:

  • go run main.go

Recibirá el siguiente resultado:

Output
Hello, World! Sammy The octopus's name is "Jesse" and is the color orange The octopus's name is "" and is the color .

Al invocar Reset, eliminó toda la información de los campos Name y Color. Cuando invoque el método String, este no imprimirá nada donde normalmente aparecen Name y Color porque los campos ahora estarán vacíos.

Conclusión

Escribir un paquete de Go es lo mismo que escribir cualquier archivo de Go, pero insertarlo en otro directorio le permite aislar el código para que pueda reutilizarse desde cualquier lugar. En este tutorial, se abordó la forma de escribir las definiciones dentro de un paquete, se demostró la manera de usar esas definiciones en otro archivo de programación de Go y se explicaron las opciones para guardar el paquete a fin de acceder a él.

0 Comments

Creative Commons License