Nesta aula, vamos explorar como declarar e usar variáveis em Go, uma das linguagens mais modernas e eficientes para desenvolvimento de software. Entender os mecanismos de declaração é fundamental para escrever código claro e correto. Vamos abordar as duas principais formas de declarar variáveis, o conceito de valores padrão (zero values), como declarar múltiplas variáveis de uma vez e as regras de escopo que determinam onde uma variável pode ser acessada.

var e :=

Em Go, existem duas maneiras principais de declarar variáveis: usando a palavra-chave var e usando o operador curto :=. A escolha entre elas depende do contexto e da necessidade de explicitar o tipo ou deixar o compilador inferi-lo.

A forma var é a mais explícita e pode ser usada tanto dentro quanto fora de funções. Ela permite declarar variáveis com ou sem valor inicial, e o tipo pode ser especificado ou inferido. Já o operador := só pode ser usado dentro de funções e sempre infere o tipo a partir do valor atribuído. É uma forma concisa e muito utilizada em Go.

package main

import "fmt"

var nome string = "João" // var com tipo explícito
var idade = 30            // var com inferência de tipo

func main() {
    var cidade string // declaração sem valor inicial (zero value)
    cidade = "São Paulo"

    pais := "Brasil" // declaração curta (só dentro de funções)

    fmt.Println(nome, idade, cidade, pais)
}

É importante notar que := declara e atribui ao mesmo tempo, e não pode ser usado para redeclarar uma variável no mesmo escopo (a menos que haja pelo menos uma nova variável). Já var pode ser usado para redeclarar, desde que no mesmo bloco e com o mesmo tipo.

Zero values

Em Go, toda variável declarada sem um valor inicial recebe automaticamente um valor padrão, chamado de zero value. Esse valor depende do tipo da variável: para tipos numéricos é 0, para booleanos é false, para strings é "" (vazio), e para ponteiros, slices, maps, canais e interfaces é nil.

Isso elimina a necessidade de inicializar variáveis manualmente e evita comportamentos indefinidos comuns em outras linguagens. Veja um exemplo:

package main

import "fmt"

func main() {
    var inteiro int
    var flutuante float64
    var booleano bool
    var texto string
    var ponteiro *int

    fmt.Printf("int: %d\n", inteiro)         // 0
    fmt.Printf("float64: %f\n", flutuante)   // 0.000000
    fmt.Printf("bool: %t\n", booleano)       // false
    fmt.Printf("string: '%s'\n", texto)      // ''
    fmt.Printf("pointer: %v\n", ponteiro)    // nil
}

Conhecer os zero values é útil para prever o comportamento de variáveis não inicializadas e para evitar erros lógicos. Por exemplo, ao declarar uma variável do tipo string sem valor, ela não será nula, mas sim uma string vazia, o que pode ser usado em condições.

Múltiplas declarações

Go permite declarar múltiplas variáveis em uma única linha ou em um bloco, o que torna o código mais limpo e organizado. Isso é especialmente útil quando você precisa de várias variáveis relacionadas.

Você pode declarar múltiplas variáveis do mesmo tipo ou de tipos diferentes, tanto com var quanto com :=. Além disso, é possível agrupar declarações com var em um bloco, similar a um import.

package main

import "fmt"

func main() {
    // Múltiplas declarações em uma linha
    var x, y int = 10, 20
    a, b := "hello", true

    // Bloco de declarações var
    var (
        nome   string = "Maria"
        idade  int    = 25
        altura float64
    )

    fmt.Println(x, y, a, b, nome, idade, altura)
}

No bloco var, cada linha declara uma variável, e você pode misturar tipos. É uma prática comum usar blocos var no início de funções ou no pacote para declarar variáveis relacionadas.

Escopo

O escopo de uma variável em Go é determinado pelo bloco onde ela é declarada. Um bloco é delimitado por chaves {} e pode ser o corpo de uma função, um if, for, switch, ou um bloco explícito. Variáveis declaradas fora de qualquer função (no pacote) têm escopo de pacote, e variáveis declaradas dentro de uma função só são acessíveis dentro dela (escopo local).

Além disso, variáveis declaradas com := dentro de um bloco (como um if) só existem naquele bloco e em seus sub-blocos. Isso ajuda a evitar vazamento de variáveis e torna o código mais seguro.

package main

import "fmt"

var global = "visível em todo o pacote" // escopo de pacote

func main() {
    local := "visível apenas em main" // escopo local

    if true {
        interno := "visível apenas neste if" // escopo de bloco
        fmt.Println(interno)
    }

    // fmt.Println(interno) // ERRO: interno não está acessível aqui
    fmt.Println(local, global)
}

func outraFuncao() {
    // fmt.Println(local) // ERRO: local não está acessível
    fmt.Println(global) // OK
}

Entender escopo é crucial para evitar conflitos de nomes e para gerenciar a memória. Em Go, variáveis locais são destruídas quando o bloco termina, a menos que sejam referenciadas por closures ou ponteiros.

Boas práticas

Ao declarar variáveis em Go, prefira usar := dentro de funções para código mais conciso, mas use var quando precisar declarar sem valor inicial ou quando o tipo for importante para a legibilidade. Evite declarar variáveis no escopo de pacote a menos que seja necessário, pois isso pode aumentar o acoplamento. Sempre inicialize variáveis com zero values se o valor inicial não fizer diferença, e use blocos var para agrupar declarações relacionadas.

Referências

Exercícios

  1. Declare uma variável nome do tipo string usando var sem valor inicial. Atribua seu nome a ela e imprima.

    ✓ Resposta:
    var nome string
    nome = "SeuNome"
    fmt.Println(nome)
  2. Usando :=, declare uma variável idade com o valor 25 e imprima.

    ✓ Resposta:
    idade := 25
    fmt.Println(idade)
  3. Declare duas variáveis a e b do tipo int em uma única linha, com valores 10 e 20 respectivamente. Troque os valores de a e b sem usar uma terceira variável.

    ✓ Resposta:
    var a, b int = 10, 20
    a, b = b, a
    fmt.Println(a, b) // 20 10
  4. Qual é o zero value de uma variável do tipo bool? Escreva um programa que declare uma variável bool sem inicializar e imprima seu valor.

    ✓ Resposta:

    O zero value de bool é false.

    var b bool
    fmt.Println(b) // false
  5. Explique o que acontece se você tentar usar := para redeclarar uma variável já existente no mesmo escopo. Dê um exemplo que cause erro e outro que funcione (com múltiplas variáveis).

    ✓ Resposta:

    Usar := para redeclarar uma variável no mesmo escopo causa erro de compilação, a menos que pelo menos uma variável do lado esquerdo seja nova. Exemplo que causa erro:

    x := 10
    x := 20 // erro: no new variables on left side of :=

    Exemplo que funciona (com nova variável):

    x := 10
    x, y := 20, 30 // ok: x é redeclarada, y é nova