O que é Variable em Go?
Uma variable (variável) em Go é um espaço nomeado na memória que armazena um valor que pode ser modificado durante a execução do programa. Toda variável em Go tem um tipo definido — seja explicitamente pelo programador ou inferido pelo compilador — e recebe um valor zero automático caso não seja inicializada explicitamente.
O sistema de variáveis de Go é projetado para ser seguro e previsível. Não existem variáveis não inicializadas com lixo de memória como em C/C++: toda variável começa com seu zero value. Além disso, o compilador exige que variáveis locais sejam utilizadas — declarar uma variável sem usá-la resulta em erro de compilação, evitando código morto.
Essa abordagem rigorosa, combinada com a inferência de tipos, torna Go uma linguagem que equilibra segurança com produtividade no dia a dia do desenvolvedor.
Formas de declarar variáveis
Declaração com var
A palavra-chave var é a forma completa de declarar variáveis:
// Com tipo explícito e valor inicial
var nome string = "Go"
// Com tipo explícito — usa zero value
var idade int // idade = 0
var ativo bool // ativo = false
var saldo float64 // saldo = 0.0
// Com inferência de tipo (tipo determinado pelo valor)
var linguagem = "Golang" // tipo inferido: string
var versao = 1.22 // tipo inferido: float64
Declaração curta com :=
O operador := combina declaração e atribuição em uma única expressão, sendo a forma mais comum em código Go idiomático:
func main() {
nome := "Go" // string
idade := 15 // int
pi := 3.14159 // float64
ativo := true // bool
fmt.Println(nome, idade, pi, ativo)
}
A declaração curta só funciona dentro de funções. Para variáveis de package, é obrigatório usar var:
package main
var versaoGlobal = "1.0" // OK: var no nível de package
// erro := "falha" // ERRO: := não permitido fora de funções
Declaração múltipla
Go permite declarar múltiplas variáveis de uma vez:
// Múltiplas com var
var (
host string = "localhost"
porta int = 8080
timeout int = 30
)
// Múltiplas com :=
x, y, z := 1, 2, 3
nome, idade := "Ana", 28
resultado, err := algumaFuncao()
A declaração múltipla com := é especialmente útil ao lidar com funções que retornam múltiplos valores — um padrão extremamente comum para tratamento de erros em Go.
Zero values
Um dos conceitos mais importantes de Go: toda variável não inicializada recebe automaticamente seu zero value:
var i int // 0
var f float64 // 0.0
var b bool // false
var s string // "" (string vazia)
var p *int // nil (ponteiro nulo)
var sl []int // nil (slice nulo)
var m map[string]int // nil (map nulo)
var ch chan int // nil (channel nulo)
var fn func() // nil (função nula)
Isso garante que não existem variáveis com lixo de memória em Go. Os zero values são usados extensivamente como valores padrão sensatos — por exemplo, um mutex com zero value já está pronto para uso, sem necessidade de inicialização:
var mu sync.Mutex // pronto para uso imediato
mu.Lock()
defer mu.Unlock()
Para entender o zero value de ponteiros, veja como nil funciona como valor padrão.
Escopo de variáveis
Go tem regras claras de escopo baseadas em blocos:
Escopo de package
Variáveis declaradas fora de funções são acessíveis por todo o package:
package main
var contador int // acessível por todas as funções deste package
func incrementar() {
contador++ // acessa variável de package
}
func mostrar() {
fmt.Println(contador) // acessa a mesma variável
}
Escopo de função e bloco
Variáveis declaradas dentro de uma func ou bloco são visíveis apenas naquele escopo:
func exemplo() {
x := 10 // visível em toda a função
if true {
y := 20 // visível apenas dentro deste if
fmt.Println(x, y) // OK
}
// fmt.Println(y) // ERRO: y não existe aqui
for i := 0; i < 5; i++ {
// i visível apenas dentro do for
}
// fmt.Println(i) // ERRO: i não existe aqui
}
Shadowing de variáveis
Shadowing ocorre quando uma variável em um escopo interno tem o mesmo nome de uma no escopo externo:
func shadowing() {
x := 10
fmt.Println(x) // 10
if true {
x := 20 // NOVA variável x — shadowing!
fmt.Println(x) // 20
}
fmt.Println(x) // 10 — x original não foi modificado
}
Shadowing é uma fonte comum de bugs sutis, especialmente com o tratamento de erros:
func perigoso() error {
var err error
if true {
// CUIDADO: := cria novo err local, não modifica o externo
resultado, err := algumaFuncao()
if err != nil {
return err // retorna o err local
}
_ = resultado
}
return err // SEMPRE nil! O err externo nunca foi atribuído
}
Para evitar esse problema, use = em vez de := quando quiser atribuir a uma variável existente, ou declare todas as variáveis no mesmo escopo.
Blank identifier (_)
O blank identifier _ é uma variável especial que descarta valores. É usado quando uma função retorna múltiplos valores, mas você não precisa de todos:
// Descartando o índice no range
for _, valor := range [slice](/glossario/slice/) {
fmt.Println(valor)
}
// Descartando um valor de retorno
_, err := fmt.Println("teste")
// Import apenas para side effects
import _ "net/http/pprof"
O compilador de Go exige que toda variável local seja usada. O _ permite satisfazer essa regra ao descartar valores indesejados sem criar variáveis inutilizadas.
Escape analysis e alocação
O compilador de Go decide automaticamente se uma variável será alocada na stack ou no heap usando escape analysis:
func naStack() int {
x := 42 // alocado na stack — não escapa
return x
}
func noHeap() *int {
x := 42 // alocado no HEAP — escapa via ponteiro
return &x // retorna ponteiro para variável local
}
Quando uma variável “escapa” do escopo da função (geralmente por retornar um ponteiro para ela), o compilador a move automaticamente para o heap. Isso é transparente para o programador, mas impacta a performance por causar alocações que o garbage collector precisa gerenciar.
Você pode verificar o escape analysis com:
go build -gcflags="-m" ./...
Variáveis e concorrência
Variáveis compartilhadas entre goroutines precisam de sincronização:
// INSEGURO: data race
var contador int
func incrementarInseguro() {
for i := 0; i < 1000; i++ {
contador++ // múltiplas goroutines modificando sem sync
}
}
// SEGURO: usando sync/atomic
var contadorSeguro int64
func incrementarSeguro() {
for i := 0; i < 1000; i++ {
atomic.AddInt64(&contadorSeguro, 1)
}
}
Use o race detector (go run -race) para detectar acessos concorrentes inseguros. Para cenários mais complexos, prefira channels ou mutex.
Variáveis vs constantes
A escolha entre variáveis e constantes é simples:
// Use const: valores que NUNCA mudam
const maxConexoes = 100
const versaoAPI = "v2"
// Use var: valores que PODEM mudar
var conexoesAtivas int
var ultimaAtualizacao time.Time
Se o valor é conhecido em tempo de compilação e nunca muda, use const. Para todo o resto, use var ou :=.
Boas práticas com variáveis
- Prefira := em funções — mais conciso e idiomático
- Declare próximo ao uso: minimize o escopo de cada variável
- Nomes curtos para escopo curto:
ipara loops,errpara erros - Nomes descritivos para escopo longo:
maxRetryAttemptsem package-level - Evite variáveis globais: dificultam testes e raciocínio
- Cuidado com shadowing: use
go vetpara detectar problemas - Agrupe vars relacionadas em blocos para organização
Para aprofundar nos fundamentos, explore o glossário completo e o guia Go para iniciantes.
Perguntas frequentes (FAQ)
Qual a diferença entre var e := em Go?
var é a declaração completa que funciona em qualquer escopo (package ou função), permite especificar o tipo explicitamente e aceita zero value sem inicialização. := é a declaração curta que só funciona dentro de funções, sempre requer um valor inicial e infere o tipo automaticamente. No dia a dia, := é preferido dentro de funções por ser mais conciso.
O que são zero values em Go?
Zero values são os valores padrão atribuídos automaticamente a variáveis não inicializadas: 0 para numéricos, false para bool, "" para string, e nil para ponteiros, slices, maps e channels. Go garante que nenhuma variável contém lixo de memória — toda variável sempre tem um valor válido desde a declaração.
O que é shadowing de variáveis e como evitar?
Shadowing ocorre quando uma variável em um escopo interno usa o mesmo nome de uma variável do escopo externo, criando uma nova variável que “esconde” a original. É uma fonte comum de bugs, especialmente com := em blocos if. Use go vet -shadow para detectar shadowing e prefira = (atribuição) em vez de := (declaração) quando quiser modificar uma variável existente.
Variáveis em Go são alocadas na stack ou no heap?
O compilador decide automaticamente usando escape analysis. Variáveis que não escapam do escopo da função ficam na stack (mais rápido). Variáveis cujos ponteiros são retornados ou armazenados em estruturas que sobrevivem ao escopo são movidas para o heap (gerenciadas pelo garbage collector). Use go build -gcflags="-m" para verificar onde cada variável é alocada.