Um pacote é composto por arquivos em Go que ficam no mesmo diretório e têm a mesma instrução de pacotes no início. Você pode incluir funcionalidades adicionais dos pacotes para tornar seus programas mais sofisticados. Alguns pacotes estão disponíveis através da Biblioteca Padrão de Go e, por isso, vêm instalados com sua instalação de Go. Outros podem ser instalados com o comando go get de Go. Você também pode compilar seus próprios pacotes Go, criando arquivos em Go no mesmo diretório em que quiser compartilhar códigos, usando a instrução de pacote necessária.

Este tutorial irá explicar sobre como escrever pacotes em Go para usar dentro de outros arquivos de programação.

Pré-requisitos

  • Configurar um ambiente de programação em Go, seguindo um dos tutoriais da série sobre Como instalar e configurar um ambiente de programação local para a linguagem Go. Criar seu espaço de trabalho em Go seguindo o Passo 5 dos tutoriais sobre Ambiente de programação local. Para seguir o exemplo e as convenções de nomenclatura neste artigo, leia a primeira seção do artigo Criando e importando pacotes.
  • Para aprofundar seu conhecimento sobre o GOPATH, leia nosso artigo Entendendo o GOPATH.

Criando e importando pacotes

Escrever um pacote é muito parecido com escrever qualquer outro arquivo em Go. Os pacotes podem conter definições de funções, tipos e variáveis que podem então ser usados em outros programas em Go.

Antes de criar um novo pacote, precisamos estar no nosso espaço de trabalho em Go. Normalmente, esse espaço fica em nosso gopath. Por exemplo, neste tutorial, chamaremos o pacote de greet. Para tanto, criamos um diretório chamado greet em nosso gopath no nosso espaço de projeto. Se nossa organização fosse a gopherguides e quiséssemos criar o pacote greet sob a organização enquanto estivéssemos usando o Github como nosso repositório de códigos, então nosso diretório se pareceria com este:

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

O diretório greet está dentro do diretório gopherguides:

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

Por fim, podemos adicionar o primeiro arquivo em nosso diretório. É considerada prática comum nomear o arquivo primary ou entry point de um pacote com o mesmo nome do diretório. Neste caso, criaríamos um arquivo chamado greet.go dentro do diretório greet:

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

Com o arquivo criado, podemos começar a escrever nosso código que queremos reutilizar ou compartilhar entre projetos. Neste caso, criaremos uma função chamada Hello que imprime Hello World.

Abra o arquivo greet.go no seu editor de texto e adicione o seguinte código:

greet.go
package greet

import "fmt"

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

Vamos desdobrar este primeiro arquivo. A primeira linha de cada arquivo precisa do nome do package [pacote] em que você está trabalhando. Como você está no pacote greet, você vai usar a palavra-chave package, seguida do nome do pacote:

package greet

Isso dirá ao compilador para tratar tudo no arquivo como sendo parte do pacote greet.

Em seguida, declare quaisquer outros pacotes que precisar usar com a instrução import. Você está usando apenas um neste arquivo — o pacote fmt:

import "fmt"

Por fim, crie a função Hello. Ela usará o pacote fmt para imprimir o Hello, World!:

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

Agora que você escreveu o pacote greet, você pode usá-lo em qualquer outro pacote que você criar. Vamos criar um novo pacote no qual você usará seu pacote greet.

Você criará um pacote chamado example, que significa que você precisa de um diretório chamado example. Crie este pacote em sua organização gopherguides, de maneira que a estrutura de diretório fique parecida com esta:

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

Agora que você tem um diretório para seu novo pacote, você pode criar o arquivo de ponto de entrada. Como este será um programa executável, é considerada como melhor prática nomear o arquivo o ponto de entrada como main.go:

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

No seu editor de texto, abra o main.go e adicione o seguinte código para chamar o pacote greet:

main.go
package main

import "github.com/gopherguides/greet"

func main() {
    greet.Hello()
}

Como você está importando um pacote, você precisa chamar a função, referenciando o nome do pacote em notação de ponto. A notação de ponto é a prática de colocar um ponto . entre o nome do pacote que estiver usando e o recurso dentro daquele pacote que você vai querer usar. Por exemplo, em seu pacote greet, você tem a função Hello como um recurso. Se quiser chamar aquele recurso, utilize a notação de ponto de greet.Hello().

Agora, abra seu terminal e execute o programa na linha de comando:

  • go run main.go

Quando fizer isso, você receberá o seguinte resultado:

Output
Hello, World!

Para ver como pode usar variáveis em um pacote, vamos adicionar uma definição de variável ao seu arquivo greet.go:

greet.go
package greet

import "fmt"

var Shark = "Sammy"

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

Em seguida, abra seu arquivo main.go e adicione a seguinte linha destacada para chamar a variável do greet.go em uma função fmt.Println():

main.go
package main

import (
    "fmt"

    "github.com/gopherguides/greet"
)

func main() {
    greet.Hello()

    fmt.Println(greet.Shark)
}

Assim que você executar o programa novamente:

  • go run main.go

Você receberá o seguinte resultado:

Output
Hello, World! Sammy

Por fim, vamos também definir um tipo no arquivo greet.go. Você criará o tipo Octopus com os campos name e color e uma função que irá imprimir os campos quando chamada:

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 o main.go para criar uma instância desse tipo no final do arquivo:

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())
}

Assim que tiver criado uma instância do tipo Octopus com oct := greet.Octopus, você poderá acessar as funções e os campos do tipo dentro do namespace do arquivo main.go. Isso permite que você escreva o oct.String() na última linha sem invocar o greet. Seria possível também, por exemplo, chamar um dos campos dos tipos como oct.Color, sem se referir ao nome do pacote greet.

O método String no tipo Octopus usa a função fmt.Sprintf para criar uma frase e returns [retorna] o resultado, uma string, para o chamador (neste caso, seu programa principal).

Quando executar o programa, você receberá o seguinte resultado:

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

Ao criar o método String no Octopus, você agora terá uma maneira reusável de imprimir informações sobre seu tipo personalizado. Se quiser alterar o comportamento deste método no futuro, você só precisará edicar esse método específico.

Código exportado

Você pode ter notado que todas as declarações no arquivo greet.go que você chamou estavam em letra maiúscula. A linguagem Go não tem o conceito dos modificadores public [públicos], private [privados], ouprotected[protegidos] como outras linguagens têm. A visibilidade externa é controlada pelo uso da letra maiúscula. Os tipos, variáveis, funções e assim por diante, que começam com uma letra maiúscula estão disponíveis publicamente, fora de seu pacote atual. Um símbolo visível fora do seu pacote é considerado comoexported`.

Caso adicione um novo método para o Octopus chamado reset, você pode chamá-lo de dentro do pacote greet, mas não do seu arquivo main.go, que está fora do pacote 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!")
}

Se tentar chamar o reset do arquivo 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()
}

Você receberá o seguinte erro de compilação:

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

Para export [exportar] a funcionalidade reset do Octopus, escreva reset com R maiúsculo:

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, você pode chamar o Reset do seu outro pacote sem receber um erro:

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())
}

Agora, se executar o programa:

  • go run main.go

Você receberá o seguinte 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 .

Ao chamar o Reset, você limpou todas as informações nos campos Name e Color. Quando chamar o método String, ele não imprimirá nada onde o Name e Color normalmente aparecem, pois os campos estão agora vazios.

Conclusão

Criar um pacote em Go é o mesmo que escrever qualquer outro arquivo em Go, mas colocá-lo em outro diretório permite que você isole o código para ser reusado em outro lugar. Este tutorial tratou de como escrever definições dentro de um pacote, demonstrou como usar essas definições dentro de outro arquivo de programação em Go e explicou as opções de onde manter o pacote para acessá-lo.

0 Comments

Creative Commons License