Declaração de variáveis: var, := e constantes

1. A declaração explícita com var

Em Go, a forma mais tradicional de declarar variáveis é usando a palavra-chave var. A sintaxe básica coloca o tipo após o nome da variável, diferentemente de linguagens como C ou Java:

var nome string
var idade int
var ativo bool

Você pode inicializar a variável no momento da declaração:

var nome string = "Maria"
var idade int = 30
var altura float64 = 1.75

Go permite declarar múltiplas variáveis em uma única linha:

var x, y int = 10, 20
var nome, email string = "João", "joao@email.com"

Para organizar declarações relacionadas, use blocos com var():

var (
    nome      string = "Ana"
    idade     int    = 25
    salario   float64
    telefone  string
)

Note que salario e telefone foram declaradas sem valor inicial — nesse caso, recebem seus zero values.

2. Inferência de tipo com :=

Go oferece uma sintaxe mais concisa com o operador :=, que combina declaração e atribuição em uma única operação, inferindo automaticamente o tipo:

nome := "Carlos"       // string
idade := 28            // int
altura := 1.80         // float64
ativo := true          // bool

Restrição importante: := só pode ser usado dentro de funções. Em escopo de pacote, você deve usar var.

package main

// nome := "João"  // ERRO! Não pode usar := fora de função
var nome = "João"    // Correto

func main() {
    sobrenome := "Silva"  // OK dentro da função
}

A inferência é inteligente: se você atribui um número inteiro, o tipo será int; se atribui uma string literal, será string. Para múltiplas variáveis:

x, y := 10, "texto"
// x é int, y é string

a, b, c := 1, 2.5, true
// a é int, b é float64, c é bool

3. Zero values e inicialização implícita

Uma característica marcante de Go é que todas as variáveis são sempre inicializadas. Se você não fornecer um valor explícito, a variável recebe o zero value do seu tipo:

var x int       // 0
var s string    // ""
var b bool      // false
var p *int      // nil
var arr [3]int  // [0, 0, 0]
var slice []int // nil

Compare as duas formas equivalentes:

var x int = 0  // explícito
var x int      // zero value, também é 0

E com :=:

x := 0  // equivalente a var x int = 0

A diferença sutil: var x int é mais claro quanto à intenção de ter um zero value, enquanto x := 0 pode sugerir que o valor 0 é significativo.

4. Constantes com const

Constantes em Go são declaradas com a palavra-chave const e não podem ser alteradas em tempo de execução:

const pi float64 = 3.14159
const nome string = "Sistema"

// Erro de compilação:
// pi = 3.14  // cannot assign to pi

Go distingue entre constantes tipadas e não tipadas (untyped):

const a = 42           // untyped integer constant
const b int = 42       // typed integer constant
const c = 3.14         // untyped floating-point constant

Constantes não tipadas oferecem flexibilidade: podem ser usadas em contextos que exigem tipos diferentes, desde que haja compatibilidade:

const valor = 100
var x int64 = valor    // OK, 100 cabe em int64
var y float64 = valor  // OK, 100 cabe em float64

Para criar enumerações, Go utiliza iota dentro de blocos const:

const (
    Segunda = iota // 0
    Terca          // 1
    Quarta         // 2
    Quinta         // 3
    Sexta          // 4
    Sabado         // 5
    Domingo        // 6
)
const (
    _  = iota             // descarta 0
    KB = 1 << (10 * iota) // 1024
    MB                    // 1048576
    GB                    // 1073741824
)

Limitação importante: constantes só funcionam com tipos básicos — números, strings e booleanos. Não é possível declarar constantes para slices, maps, structs ou funções.

5. Escopo e visibilidade de variáveis

Go possui regras claras de escopo baseadas em blocos {}:

package main

var versao = "1.0" // variável de pacote (package-level)

func main() {
    var mensagem = "Olá" // variável local
    {
        var interna = "visível apenas aqui"
        println(mensagem) // OK, escopo externo
        println(interna)  // OK
    }
    // println(interna) // ERRO: interna não está neste escopo
}

A visibilidade em Go é controlada pela primeira letra do identificador:

  • Maiúscula: exportado (visível fora do pacote)
  • Minúscula: não exportado (visível apenas dentro do pacote)
var NomeGlobal = "Visível em outros pacotes"   // exportado
var nomeLocal = "Visível apenas neste pacote"   // não exportado

Cuidado com shadowing (sombreamento) — declarar uma variável com o mesmo nome em um escopo interno:

func main() {
    x := 10
    if true {
        x := 20 // shadowing: esta x esconde a exterior
        println(x) // 20
    }
    println(x) // 10 (a variável original permanece)
}

6. Boas práticas e armadilhas comuns

Quando usar var vs :=:

  • Use var para valores zero ou quando o tipo precisa ser explícito:
    go var err error // zero value nil, tipo explícito var config Config

  • Use := dentro de funções para declarações curtas e diretas:
    go nome := "João" resultado := calcular(10, 20)

Evite redeclaração acidental com :=:

func main() {
    x := 10
    x := 20 // ERRO: no new variables on left side of :=

    // Correto: pelo menos uma variável deve ser nova
    x, y := 20, "novo" // OK, y é nova
}

Use _ (blank identifier) para descartar valores:

valor, _ := strconv.Atoi("42") // ignora o erro
_, err := algumMetodo()         // ignora o valor de retorno

Inicialização inline com if e switch:

if err := processar(); err != nil {
    log.Fatal(err)
}
// err não existe mais aqui

switch v := rand.Intn(10); v {
case 0:
    println("zero")
default:
    println(v)
}

Essa técnica limita o escopo da variável ao bloco condicional, evitando poluição do escopo externo.

Referências