Usando Pacotes (Módulos) em Go
A partir da versão 1.11 do GoLang, nós fomos introduzidos ao conceito de módulos, que representam uma unidade de código versionada capaz de gerenciar pacotes e dependências.
Os módulos nos permitem que você escreva, distribua e use bibliotecas de maneira organizada e controlada, sem depender da antiga variável GOPATH
.
No GoLang, um módulo é composto por 3 características principais:
1️⃣ Um Módulo é composto de:
- Um diretório raiz contendo o código em Go, e um arquivo chamado
go.mod
, - Além disso, eles podem conter múltiplos pacotes dentro de si.
2️⃣ Existência de pacotes internos:
- Contém um conjunto de arquivo
.go
no mesmo diretório, - Além disso, um módulo pode ter vários pacotes internos.
3️⃣ Dependência:
- Um módulo pode importar diversos outros módulos dentro de si,
- O arquivo
go.mod
tem a missão de listar todas as dependências externas do seu módulo principal.
Agora que você já tem mais ou menos uma noção do que seja um pacote e um módulo em GoLang, vamos aprender com mais detalhes o funcionamento de um pacote 🤓
Mas antes, precisamos criar nossa pasta do projeto!
Criando seu projeto de testes
Dentro da pasta JornadaGoLang, nós iremos criar uma nova pasta chamada de 20-modulos-em-go
, onde dentro dela, vamos criar o nosso arquivo main.go
:
package main
func main() {
}
Feito isso, vamos conhecer um pouco mais sobre os pacotes em Go 😉
📦 Pacotes e Visibilidade em Go (com Módulos)
Em Go, tudo faz parte de um pacote. Um pacote é um conjunto de arquivos .go
que pertencem a um mesmo namespace
e compartilham o mesmo código.
Por exemplo, quando você cria um novo programa em Go, o ponto de entrada dessa aplicação está sempre no pacote main
:
package main
import "fmt"
func main() {
fmt.Println("Hello, Go!")
}
E como nós já sabemos (se ainda não sabe, recomendo começar na primeira lição desta jornada), o package main
diz ao compilador que o arquivo atual é um executável.
Além disso, o comando import "fmt"
, diz ao compilador que nós estamos importando um pacote padrão do Go ao nosso projeto.
É importante ressaltar que, quando você cria um novo arquivo .go
que contém funções, variáveis e estruturas que começam com letra maiúscula elas são exportadas (públicas).
Já às que começam com letras minúsculas, são privadas ao pacote, vejamos:
package meu_pacote
// Exportado (público)
func MinhaFuncao() {
fmt.Println("Função Exportada!")
}
// Privado ao pacote
func minhaFuncaoPrivada() {
fmt.Println("Apenas para este pacote!")
}
No código acima, nós criamos um novo pacote chamado de meu_pacote
, que conta com duas funções:
MinhaFuncao()
: função pública que pode ser exportada (acessada) por outros arquivos .go
que a implementam (fazem o uso dela).
minhaFuncaoPrivada()
: função privada que só pode ser acessada por outras funções que existem dentro do seu arquivo .go
.
Isso significa dizer que, se outro pacote importar meu_pacote
, ele só poderá acessar MinhaFuncao()
.
Além disso, é importante ressaltar que o pacote do exemplo acima (meu_pacote
), por si só, não pode ser executado de forma direta pelo compilador do Go (go build...
), pois ele é apenas um arquivo extensor (pacote), que tem por objetivo servir novas funcionalidades a arquivos em Go que contam com a função main()
e se tratam de arquivos executáveis (implementam package main).
Pense em um pacote como uma espécie de plugin de um software, ou uma DLC de um jogo de videogame, onde sozinhos eles não fazem nada, pois dependem de outro código (software principal ou jogo principal) para serem utilizados.
Supondo que eu queria fazer o uso do meu_pacote dentro do meu main.go, como isso ficaria?
Simples, a primeira coisa que você precisa fazer é criar dentro da pasta do seu projeto um novo arquivo chamado meu_pacote.go
dentro de uma pasta chamada meu_pacote
com o mesmo código que criamos anteriormente:
meu_projeto/
│── go.mod
│── main.go
└── meu_pacote/
└── pacote.go
package meu_pacote
import "fmt"
// Exportado (público)
func MinhaFuncao() {
fmt.Println("Função Exportada!")
}
// Privado ao pacote
func minhaFuncaoPrivada() {
fmt.Println("Apenas para este pacote!")
}
Em seguida, dentro do seu main.go
, iremos inserir o seguinte código abaixo:
package main
import (
"fmt"
"meu_projeto/meu_pacote" // Importando o pacote
)
func main() {
meu_pacote.MinhaFuncao() // OK: Função pública
// meu_pacote.minhaFuncaoPrivada() // Erro: Não exportada
fmt.Println("Executando main.go!")
}
Por fim, antes de executar seu projeto, certifique-se de que você inicializou o seu módulo (pasta do projeto):
go mod init meu_projeto
E por fim, execute seu projeto via terminal da seguinte forma:
go run main.go
Lembre-se de que:
- Funções exportadas (públicas) começam com letra maiúscula (
MinhaFuncao
). - Funções privadas só podem ser usadas dentro do próprio pacote (
minhaFuncaoPrivada
).
E já que falamos sobre um jogo de videogame, vamos imaginar um outro exemplo um pouco mais divertido 🤖
Imagine um jogo onde você tem um pacote chamado fisica
que contém funções para calcular a gravidade e colisões. O jogo principal (package main
) usaria esse pacote para simular o ambiente, mas o pacote fisica
sozinho não pode ser executado.
Sendo assim, dentro da pasta fisica
, nós temos um arquivo chamado gravidade.go
com a seguinte lógica:
// arquivo: fisica/gravidade.go
package fisica
// QuedaLivre calcula a distância percorrida em queda livre
func QuedaLivre(tempo float64) float64 {
g := 9.8 // Aceleração gravitacional (m/s²)
return 0.5 * g * (tempo * tempo)
}
Já no código principal do jogo, nós temos essa lógica:
package main
import (
"fmt"
"meu_modulo/fisica"
)
func main() {
distancia := fisica.QuedaLivre(2)
fmt.Println("Objeto caiu:", distancia, "metros")
}
⚠️ Se tentarmos rodar go run fisica/gravidade.go
, dará um erro de compilação, pois ele não contém package main
. Sendo assim, ele não pode ser executado sozinho, assim como uma DLC sem o jogo base.
Ah, e não se esqueça de inicializar o seu módulo (pasta do projeto) antes de executar seu main.go
😄
go mod init meu_projeto
// Em seguida use
go run main.go
🔄 Criando um Pacote Reutilizável (com Módulos)
Antes de mais nada, esse tópico já foi discutido em tópicos anteriores, sendo assim, a ideia deste tópico é te explicar um passo a passo de como criar pacotes reutilizáveis em Go.
Lembrando que todo pacote em GoLang pode ser reutilizável por outros pacotes e módulos, ok?
Passo 1: Criando seu Módulo
Um módulo em Go é a pasta do seu projeto, sendo assim, precisamos criar essa pasta e inicializar ela no terminal:
mkdir meu_modulo
cd meu_modulo
go mod init github.com/seu-usuario/meu_modulo
Isso cria um arquivo go.mod
com informações do módulo.
Obervação: cada linha do exemplo acima deve ser inserida no seu terminal de forma separada.
Passo 2: Criando um Pacote
No diretório do módulo, crie um diretório chamado calculadora e adicione um arquivo chamado calculadora.go
, com a seguinte lógica:
package calculadora
// Soma retorna a soma de dois números
func Soma(a, b int) int {
return a + b
}
Passo 3: Usando seu Pacote
Agora, em outro diretório, crie um novo módulo e importe meu_modulo
para dentro de si:
mkdir meu_projeto
cd meu_projeto
go mod init meu_projeto
go get github.com/seu-usuario/meu_modulo
Agora, crie um main.go
:
package main
import (
"fmt"
"github.com/seu-usuario/meu_modulo/calculadora"
)
func main() {
resultado := calculadora.Soma(2, 3)
fmt.Println("Resultado:", resultado)
}
E por fim, não se esqueça de executar o comando go run
para executar seu projeto 😄
Entretanto, você pode ter problemas para importar o seu módulo usando a declaração github.com/seu-usuario
.
Mas o que vem a ser essa declaração? E se meu projeto não existir no github, somente local? O que eu faço?
Módulos Versionados no GitHub
Quando você deseja criar um módulo em Go versionado e publicá-lo no GitHub, você precisa definir um namespace único para ele. Normalmente, esse namespace segue o formato:
github.com/seu-usuario/nome-do-modulo
Mas daí você pode estar se perguntando: o que colocar em seu-usuario?
No caso do seu-usuario
, você deve substituir para o nome do seu usuário na plataforma do GitHub.
E para pegar o nome do seu usuário é bem simples, basta entrar no GitHub, fazer login com a sua conta, clicar em cima da sua foto no canto superior direito e clicar no botão Profile:

Automaticamente você será redirecionado para a página principal do seu perfil, onde na URL do navegador, estará o seu nome de usuário:

Porém, você precisa se certificar de que o seu pacote está publicado no GitHub. E para isso, você precisará fazer uma série de outros passos para publicá-lo.
Mas fique tranquilo que aqui no Portal da Micilini, nós temos uma jornada que vai falar tudo o que você precisa saber sobre Git & GitHub, vale a pena conferir 😉
Importando um módulo sem ele estar no GitHub
Beleza, mas supondo que você não tenha um módulo publicado no GitHub, e agora? 😶
Nesse caso em específico, você pode definir o nome do módulo com qualquer namespace interno.
E isso quer dizer que você precisa seguir um padrão similar a este, onde estamos seguindo com um domínio local:
go mod init local/meu_projeto
Para que você entenda como isso é feito, vamos fazer uma passo a passo 😉
1️⃣ Criando o Projeto: Dentro da pasta do seu projeto, vamos inicializar o nosso módulo:
mkdir meu_projeto && cd meu_projeto
go mod init local/meu_projeto
Os comandos acima, irão inicializar o seu módulo gerando o arquivo go.mod
com uma estrutura similar a esta:
module local/meu_projeto
go 1.22
Note que criamos um namespace interno chamado de local
.
2️⃣ Criando um Pacote (pacote.go): Como você já sabe, precisamos criar o arquivo que representa o nosso pacote:
package meu_pacote
import "fmt"
// Função pública
func OlaMundo() {
fmt.Println("Olá, mundo do meu pacote!")
}
Em seguida, não se esqueça de criar o seu arquivo main.go
:
package main
import (
"local/meu_projeto/meu_pacote"
)
func main() {
meu_pacote.OlaMundo()
}
E pronto, seu módulo será encontrado facilmente pelo compilador 🙃
Criando um módulo local reutilizável em Go
Se você quiser criar um módulo local em outro projeto mas sem publicá-lo no GitHub, você pode usar o comando replace
dentro do go.mod
do projeto que vai consumir o seu módulo.
Para isso, vamos começar criando um novo módulo simples que será utilizado em outro projeto:
/home/user/meu_modulo/
│── go.mod
│── meu_pacote/
│ ├── pacote.go
Dentro da pasta do seu módulo (meu_modulo
), vamos fazer as configurações iniciais:
go mod init local/meu_modulo
Já dentro do arquivo pacote.go
, vamos inserir a seguinte lógica:
package meu_pacote
import "fmt"
// Função exportada
func OlaMundo() {
fmt.Println("Olá, mundo do meu módulo local!")
}
Agora, vamos criar um segundo projeto que será responsável por consumir este módulo que acabamos de criar:
/home/user/meu_projeto/
│── go.mod
│── main.go
Com o terminal aberto vamos inicializar este módulo:
cd /home/user/meu_projeto
go mod init local/meu_projeto
Com o arquivo go.mod
já criado, devemos atualizá-lo para que ele possa consumir o nosso módulo localmente:
module local/meu_projeto
go 1.22
replace local/meu_modulo => /home/user/meu_modulo
Isso força o Go a buscar o módulo localmente, na pasta especificada.
Agora, dentro do main.go
do nosso projeto, vamos usar a seguinte lógica:
package main
import (
"local/meu_modulo/meu_pacote"
)
func main() {
meu_pacote.OlaMundo()
}
Por fim, não se esqueça de executar um go tidy
e rodar seu projeto 😉
go mod tidy # Garante que todas as dependências estão corretas
go run main.go
O comando replace local/meu_modulo => /caminho/para/modulo
permite que o Go encontre um módulo local, atuando de forma extremamente útil quando você quer testar um módulo antes de publicá-lo no GitHub.
Ou seja, seu código será usado internamente, sem necessidade de um repositório remoto.
Diferenças entre Pacotes, Módulos e Bibliotecas em Go
Você sabia que apesar dos pacotes, módulos e até bibliotecas serem tudo "farinha do mesmo saco", eles possuem diferenças particulares?
Exato, começando com nosso amigo pacotes, como você já sabe, eles contam com as seguintes características:
🔹 Menor unidade organizacional de código em Go.
🔹 Todo arquivo .go
pertence a um pacote.
🔹 Pode ser importado e reutilizado dentro de um módulo.
🔹 Define visibilidade de funções, structs e variáveis (público ou privado).
Vejamos um exemplo de um arquivo .go
que representa um pacote:
// arquivo: calculadora.go
package calculadora
// Soma é exportada (pública)
func Soma(a, b int) int {
return a + b
}
// subtracao é privada ao pacote
func subtracao(a, b int) int {
return a - b
}
No caso dos módulos, eles representam um projeto em Go, sendo considerados:
🔹 Um conjunto de pacotes organizados com controle de versão.
🔹 São criado por meio do comando go mod init
.
🔹 Contém um arquivo go.mod
, que define o nome do módulo e as dependências.
Exemplo de um módulo criado com Go:
go mod init github.com/seu-usuario/meu_modulo
Ou seja, módulo é aquilo que você usa, pacote é aquilo que você importa dentro de um módulo para usar 😊
Por fim, temos as famosas bibliotecas, que nada mais são do que um conjunto de pacotes dentro de um módulo com código reutilizável.
🔹 Pode ser distribuída para outros projetos.
🔹 Não contém um package main
, pois não é um executável.
Basicamente uma biblioteca é um conjunto de diversos outros pacotes que juntos, se transformam numa espécie de canivete suíço:

Vejamos um exemplo de como pode ser estruturada uma biblioteca em Go:

Note que ela contém diversos pacotes dentro de si, ao mesmo tempo que não conta com um arquivo main.go
, impedindo que a biblioteca possa ser executada.
🌎 Criando & Instalando um Pacote do GitHub
Observação: para prosseguir com os ensinamentos deste tópico, é necessário que você possua um mínimo de conhecimento sobre como usar Git & GitHub. Se ainda não tem, recomendo dar uma olhada na jornada de Git & GitHub do Portal da Micilini.
Supondo que você tenha um módulo e queria jogá-lo para o GitHub, basta abrir o terminal dentro da pasta do seu projeto e seguir os passos abaixo:
git init
git add .
git commit -m "Primeira versão"
git branch -M main
git remote add origin https://github.com/seu-usuario/meu_modulo.git
git push -u origin main
Com seu módulo já upado para a plataforma, caso você queira importá-lo para um outro projeto em Go, basta abrir o terminal na pasta do seu projeto e executar um go get
, por exemplo:
go get github.com/seu-usuario/meu_modulo@latest
Isso adiciona o pacote ao go.mod
e permite usá-lo. Lembrando que o go get
pode ser usado para baixar outros pacotes de terceiros e seu projeto em Go.
Como você já viu em lições passadas, nós usamos o comando go get
para baixar pacotes de terceiros (e nossos também, desde que eles estejam públicos no GitHub).
🌎 Principais Plataformas para Encontrar Repositórios Go
Diferentes de outras linguagens de programação, no caso do Go, os pacotes e módulos são distribuídos de forma descentralizada, mas há algumas plataformas onde você pode encontrar repositórios públicos:
Repositório da lição
Todos os arquivos relacionados com esta lição, podem ser encontrados nos seguintes repositórios abaixo:
Conclusão
Nesta lição, você aprendeu um pouco mais sobre módulos, pacotes e bibliotecas em GoLang.
Pacote: é uma unidade de código reutilizável dentro de um módulo (como um plugin ou DLC).
Módulo: é um conjunto de pacotes versionados e gerenciados com go.mod
, geralmente executável.
Biblioteca: é um módulo que oferece funcionalidades reutilizáveis para vários projetos.
Até a próxima lição 😄