Manipulando Arquivos .env em Go
Durante a sua jornada como desenvolvedor em Go, você irá se deparar com alguns projetos e bibliotecas que fazem o uso de arquivos .env
.
Esses arquivos são chamados de variáveis de ambiente do projeto, e são amplamente utilizados em aplicações para manter informações sensíveis ou específicas daquele projeto em questão.
Nesta lição, você vai aprender a não só criar, como também usar tais arquivos em seus projetos feitos om GoLang.
Vamos nessa? 😆
Criando seu projeto de testes
Dentro da pasta JornadaGoLang, nós iremos criar uma nova pasta chamada de 15-manipulando-env
, onde dentro dela, vamos criar o nosso arquivo main.go
:
package main
func main() {
}
Feito isso, vamos conhecer um pouco mais sobre os arquivos .env
😉
O que são arquivos .env?
Arquivos .env
(do inglês "environment", ou "ambiente") são usados para armazenar variáveis de ambiente em formato de texto simples.
Diferente das variáveis de ambiente do sistema operacional, os arquivos .env
são mais flexíveis, podendo ser passados de máquina para máquina, de desenvolvedor para desenvolvedor, de projeto para projeto.
Enquanto as variáveis de ambiente do sistema operacional, estão de certa forma, "mais presas" em cada sistema.
No caso dos arquivos .env
, eles são usados para o armazenamento de configurações e informações sensíveis do projeto, tais como:
- Chaves de API
- Credenciais de banco de dados
- URLs de serviços externos
- Configurações específicas para desenvolvimento, teste ou produção
E como dito anteriormente, tais arquivos te ajudam a separar a configuração do código-fonte, proporcionando:
Segurança: Mantém informações sensíveis fora do código, evitando expô-las em repositórios.
Flexibilidade: Permite trocar configurações sem precisar alterar o código.
Facilidade de Deploy: Facilita a adaptação entre ambientes (desenvolvimento, staging, produção).
Utilizando arquivos .env no GoLang
No momento atual da versão do GoLang (1.24) não existe uma biblioteca padrão (advinda da própria instalação do Go) que seja capaz de implementar esses arquivos .env em nossos projetos.
O que nos obriga (pela primeira vez na jornada) a implementar uma biblioteca de terceiros!
Para isso, dentro da pasta do seu projeto, navegue com o terminal dentro dela, e em seguida, você vai precisar criar os arquivos iniciais da seguinte forma:
go mod init manipulando-env
De forma automática será criado um novo arquivo chamado go.mod
dentro da pasta do seu projeto, que será necessário para instalarmos novos pacotes.
Em seguida, não se esqueça de executar o comando go mod tidy
para instalar os pacotes iniciais da aplicação:
go mod tidy
Agora que já temos isso, estamos prontos para instalar o nosso pacote:
go get github.com/joho/godotenv
Após a instalação da biblioteca, já estamos prontos para importarmos arquivos .env
para dentro do nosso projeto 😉
Por que usar variáveis de ambiente?
Vamos supor que você tenha uma chave de acesso que será usada por uma API durante a sua aplicação:
Autorization Key: FF908-98UIO-KK97
Vamos supor também, que em diferentes partes do seu código, você precisa acessar essa chave de acesso. Então vamos imaginar que temos 5 módulos (arquivo .go) que fazem o uso dessa chave dentro da nossa aplicação:
- Dashboard.go
- Usuarios.go
- Produtos.go
- Servicos.go
- Configuracoes.go
Cada qual fazendo uma chamada em um endpoint diferente de uma mesma API, como por exemplo:
/getDashboardData
/getUsuarios
/getProdutos
/getServicos
/getConfiguracoes
Como em cada endpoint você precisa passar a sua chave de acesso (Autorization Key
) no header da sua requisição, você pode enviá-la de algumas formas diferentes:
- Você pode inserir essa chave na chamada de cada endpoint.
- Você pode salvar essa chave na memória, e passá-la para cada uma das suas classes ou funções.
- Você pode criar um
config.js
para armazenar essa chave.
Apesar de todas as estratégias acima funcionarem muito bem, por motivos óbvios (e já explicados anteriormente), é claro que a melhor opção seria a criação de um arquivo .env
🙂
Ou seja, em vez de você ter que ficar repetindo a mesma chave de acesso em todos os seus arquivos .go
. O problema é que se a sua chave de acesso mudar, você precisar alterá-la em todos os arquivos onde ela está declarada.
Usando arquivos .env
, todos consomem da mesma fonte, e se você precisar alterar alguma coisa, você só precisará altera uma única vez.
Criando um arquivo .env
Agora que você já sabe da importância de um arquivo .env
, vamos criar um!
Para isso, dentro da pasta do seu projeto, basta criar um novo arquivo chamado .env
.
A estrutura de um arquivo desses segue uma estrutura de chave e valor, tal como essa:
NOME=micilini
RANK=100
SECRET="Micilini é DEZ!"
KEY="@090OALK''JJ3"
SITE_APP=https://micilini.com/
Note que todas as chaves estão usando o operador de atribuição (=
) e definindo seus valores, onde cada um deles estão sendo separados por uma quebra de linha.
Note também que podemos definir nossas chaves dentro de aspas duplas, o que representa uma string
de fato (Observação: isso não é recomendado, mas funciona em alguns casos).
E pronto, seu arquivo .env
acaba de ser criado com sucesso. Agora vamos ver como carregar essas informações para dentro do seu projeto em Go 🤓
Carregando um arquivo .env
Para carregar um arquivo .env
, você vai precisar importar a biblioteca que acabamos de instalar, e mais algumas outras, como por exemplo:
fmt
: biblioteca para mostrar mensagens no console. Usaremos ela para mostrar os valores armazenados nas chaves dos arquivos.env
.os
: biblioteca para carregar arquivos do sistema operacional. Usaremos ela para pegar o conteúdo existente dentro do arquivo.env
."github.com/joho/godotenv"
: biblioteca para carregar arquivos.env
. É a bilioteca que realiza a leitura de fato.
Vejamos como isso pode ser feito:
package main
import (
"fmt"
"os"
"github.com/joho/godotenv"
)
func main() {
// Carrega as variáveis do arquivo .env
err := godotenv.Load()
if err != nil {
fmt.Println("Erro ao carregar o arquivo .env")
return
}
// Acessa as variáveis
dbUser := os.Getenv("NOME")
dbPass := os.Getenv("RANK")
apiKey := os.Getenv("SITE_APP")
fmt.Println("Usuário:", dbUser)
fmt.Println("Rank:", dbPass)
fmt.Println("URL:", apiKey)
}
Começando pelo godotenv.Load()
, nós enviamos uma instrução para que a biblioteca carregue um arquivo .env
que está localizado dentro no mesmo diretório do seu main.go
.
Se ele não for encontrado, uma mensagem de erro será mostrada.
Em seguida, por meio do os.Getenv()
devemos informar a chave que queremos carregar, que nesse caso, são as chaves que definimos no arquivo .env
.
Por fim, estamos mostrando no terminal o conteúdo que está sendo armazenado em cada uma dessas chaves:
Usuário: micilini
Rank: 100
URL: https://micilini.com/
Incrível, não acha? 😄
Trabalhando com variáveis de ambiente em diferentes ambientes
Em tópicos anteriores foi dito que nós podemos definir diversas variáveis de ambiente em diferentes tipos de ambiente, como ambiente de desenvolvimento, de testes e de produção.
Mas como isso funciona na prática? Simples, você pode criar diversos arquivos .env
com nomes especificos, por exemplo:
.env
(Padrão da aplicação).env.example
(Arquivo de exemplo, com chaves vazias).env.local
(Este arquivo é carregado para todos os ambientes, exceto teste.).env.development
(Este arquivo é carregado em ambientes de desenvolvimento).env.test
(Este arquivo é carregado em ambientes de testes).env.production
(Este arquivo é carregado em ambientes de produção)
Vamos ver um exemplo prático entre algumas diferenças dos arquivos .env
:
.env.production
:
API_BASE_URL=https://api.producao.com/
.env.development
:
API_BASE_URL=https://api.desenvolvimento.com/
Quando sua aplicação estiver em modo de desenvolvimento ou produção, a sua lógica do GoLang deverá escolher automaticamente qual arquivo que será carregado
Existem ainda aquelas aplicações que possuem um arquivo chamado de .env.example
, que representa um exemplo de quais chaves deverão ser setadas dentro de um arquivo .env
:
APP_NOME=
APP_RANK=
APP_SECRET=
APP_KEY=
APP_SITE=
Note que as chaves estão atreladas a valores vazios, pois o objetivo desse arquivo é apenas instruir o desenvolvedor sobre quais variáveis o sistema precisa para rodar.
Carregando um arquivo .env customizado
Como dito anteriormente, você pode ter diferentes arquivos .env
para ambientes diferentes. Mas uma pergunta que fica é... como carregar um arquivo .env
específico?
Simples, supondo que você tenha os seguintes arquivos .env
no seu projeto:
.
├── main.go
├── .env.development
└── .env.production
Você poderia usar um código como esse para realizar a importação das variáveis de ambiente:
package main
import (
"fmt"
"log"
"os"
"github.com/joho/godotenv"
)
func main() {
// Define qual arquivo carregar com base em um argumento ou variável
envFile := ".env.development"
if len(os.Args) > 1 && os.Args[1] == "prod" {
envFile = ".env.production"
}
// Carrega o arquivo .env específico
err := godotenv.Load(envFile)
if err != nil {
log.Fatalf("Erro ao carregar o arquivo %s: %v", envFile, err)
}
// Lê as variáveis de ambiente
fmt.Println("Ambiente:", os.Getenv("APP_ENV"))
fmt.Println("Usuário do Banco de Dados:", os.Getenv("DB_USER"))
fmt.Println("Senha do Banco de Dados:", os.Getenv("DB_PASS"))
}
No caso do comando Load()
, ele aceita o nome do arquivo ou o caminho de onde o arquivo .env
se encontra.
Supondo que o seu arquivo .env
esteja salvo em uma pasta diferente, basta seguir o exemplo abaixo:
package main
import (
"fmt"
"log"
"os"
"github.com/joho/godotenv"
)
func main() {
// Define o caminho para o arquivo .env
envFile := "configs/.env.development"
// Carrega o arquivo .env de um diretório específico
err := godotenv.Load(envFile)
if err != nil {
log.Fatalf("Erro ao carregar o arquivo %s: %v", envFile, err)
}
// Acessa as variáveis de ambiente
fmt.Println("Ambiente:", os.Getenv("APP_ENV"))
fmt.Println("Usuário do Banco de Dados:", os.Getenv("DB_USER"))
}
Fácil, não acha? 😋
Criando variáveis de ambiente de uma maneira saudável
Para criar uma aplicação organizada, saudável e de fácil manutenção, você precisa mapear suas variáveis de ambiente com nomes legíveis e sempre em letras maiúsculas.
Dê nomes descritivos às suas variáveis de ambiente e que fazem sentido não só pra você, quanto também para outros desenvolvedores que irão trabalhar em cima do seu código.
Por exemplo, se você estiver usando uma API voltada para uma aplicação de restaurante, em vez de mapear a sua variável como API_KEY
, opte por um nome mais especifico e legível como: RESTAURANT_API_KEY
.
Uma outra boa prática está relacionado ao não adicionamento de strings
ou caracteres que possuam espaço em seus valores, como por exemplo:
// Evite isso
API_KEY="12345"
SECRET="oim 92m3d 29nd2 nd9d"
// Faça isso em vez disso
API_KEY=12345
SECRET=oim92m3d29nd2nd9d
É importante ressaltar que os valores existentes dentro dos arquivos .env
são tratados como strings
, portanto, se você colocar seus valores entre aspas (sejam elas duplas ou simples), ou quem talvez inserir espaços em branco, tais valores podem gerar resultados inesperados e bugs difíceis de rastrear.
Vai por mim, experiência própria...
Importante: Não faça o upload de arquivos .env para repositórios online
Sim, é isso mesmo que você leu!
Arquivos .env
costumam ter informações sensíveis, tanto é que no arquivo .gitignore
do Git, por padrão tais arquivos NÃO devem ser upados para repositórios públicos ou privados.
Sendo assim, antes de realizar um GIT PUSH
ou um PULL REQUEST
, certifique-se de que o arquivo .env
não está sendo enviado também. (muito menos o .env.development, .env.test, .env.production... mas o .env.example pode passar)
Beleza... então como eu faço para enviar o arquivo .env
, uma vez que a minha aplicação depende dele?
Se você trabalha com um time de desenvolvimento, sempre passe esses arquivos de maneira segura (e-mail, slack ou qualquer outro canal de segurança) entre vocês.
Se é você quem coloca sua aplicação online, evite incluir o envio desse arquivo diretamente em técnicas de CI/CD, opte por fazer o upload na pasta raiz do seu projeto de maneira manual.
Como alternativa você pode enviar o arquivo .env.example
em repositório online, para que os futuros devs ou arquitetos que forem clonar o seu repositório, tenham uma ideia de quais variáveis de ambiente a sua aplicação necessite para rodar.
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 a importar arquivos .env
para dentro do seu projeto em Go.
Até a próxima 😌