Variáveis e declarações
Nesta aula, você aprenderá a declarar variáveis em Go usando as formas `var` e `:=`, entenderá os valores zero padrão, como declarar múltiplas variáveis de uma vez e como o escopo afeta a visibilidade. O conteúdo inclui exemplos práticos e exercícios com respostas.
Nesta aula, vamos explorar como declarar e usar variáveis em Go, uma das linguagens mais modernas e eficientes para desenvolvimento de sistemas. Dominar as declarações de variáveis é fundamental para escrever código claro e seguro, aproveitando o sistema de tipos estático e a inferência de tipos que Go oferece.
Go possui duas formas principais de declarar variáveis: a palavra-chave var, que permite declarações explícitas com tipo, e o operador curto :=, que infere o tipo a partir do valor atribuído. Além disso, entender os valores zero, declarações múltiplas e escopo é essencial para evitar erros comuns e escrever código idiomático.
var e :=
A forma mais básica de declarar uma variável em Go é usando a palavra-chave var. Ela pode ser usada dentro de funções ou no nível do pacote. A sintaxe geral é var nome tipo, e opcionalmente pode-se inicializar a variável com um valor. Se o valor for fornecido, o tipo pode ser omitido, pois Go o infere.
Já o operador curto := só pode ser usado dentro de funções (escopo local) e combina declaração e atribuição em um único passo. Ele infere o tipo da variável a partir do valor atribuído. É a forma mais comum e idiomática para declarar variáveis locais.
package main
import "fmt"
var globalVar = "Eu sou global" // declaração com var no nível do pacote
func main() {
var nome string = "Alice" // var com tipo explícito
var idade = 30 // var com inferência de tipo
cidade := "São Paulo" // operador curto (apenas dentro de funções)
fmt.Println(nome, idade, cidade)
}
Zero values
Em Go, toda variável declarada sem um valor explícito recebe automaticamente um valor zero (zero value). Isso elimina a possibilidade de variáveis não inicializadas, um problema comum em outras linguagens. O valor zero depende do tipo:
- Tipos numéricos (int, float, etc.):
0 - Booleanos:
false - Strings:
""(string vazia) - Ponteiros, slices, maps, canais, interfaces, funções:
nil - Structs: todos os campos com seus valores zero
Exemplo:
package main
import "fmt"
func main() {
var i int
var f float64
var b bool
var s string
var p *int
fmt.Printf("int: %v\n", i) // 0
fmt.Printf("float64: %v\n", f) // 0
fmt.Printf("bool: %v\n", b) // false
fmt.Printf("string: %q\n", s) // ""
fmt.Printf("pointer: %v\n", p) // nil
}
Múltiplas declarações
Go permite declarar múltiplas variáveis em uma única linha, separando-as por vírgulas. Isso é útil para inicializar várias variáveis de uma vez, especialmente quando uma depende da outra (por exemplo, em funções que retornam múltiplos valores).
Além disso, é possível usar a sintaxe var ( ... ) para declarar várias variáveis em bloco, geralmente no nível do pacote, para melhor organização.
package main
import "fmt"
var (
nome = "João"
idade = 25
altura = 1.75
)
func main() {
a, b := 10, 20 // múltiplas declarações com :=
var x, y int = 30, 40 // múltiplas declarações com var
c, d := trocar(a, b) // comum com retornos múltiplos
fmt.Println(a, b, c, d)
fmt.Println(nome, idade, altura)
}
func trocar(x, y int) (int, int) {
return y, x
}
Escopo
O escopo de uma variável define onde ela pode ser acessada. Em Go, o escopo é determinado pelo bloco onde a variável é declarada. Um bloco é delimitado por chaves {} (por exemplo, corpo de função, if, for, switch).
Variáveis declaradas no nível do pacote (fora de qualquer função) são acessíveis em todo o pacote. Variáveis declaradas dentro de uma função são locais à função, e variáveis declaradas dentro de blocos internos (como if ou for) são acessíveis apenas naquele bloco e sub-blocos.
É importante lembrar que variáveis declaradas com := só existem dentro do bloco onde foram declaradas. Além disso, Go permite sombreamento (shadowing): uma variável em um escopo interno pode ter o mesmo nome que uma variável em escopo externo, ocultando-a temporariamente.
package main
import "fmt"
var x = "global"
func main() {
fmt.Println(x) // global
if true {
x := "local" // sombreamento (shadowing)
fmt.Println(x) // local
}
fmt.Println(x) // global (a variável local não afetou a global)
}
Boas práticas
Prefira usar := para declarações locais, pois é mais conciso. Use var para declarações no nível do pacote e quando precisar declarar uma variável sem inicializá-la (para que receba o valor zero). Evite sombreamento desnecessário, pois pode causar confusão. Agrupe declarações de variáveis relacionadas em blocos var() para melhor legibilidade.
Referências
- Effective Go - Variables
- Go Specification - Variables
- Go Specification - Short variable declarations
- Go Specification - Zero value
- Go Specification - Declarations and scope
- A Tour of Go - Variables
Exercícios
-
Declare uma variável
nomedo tipo string com valor "Maria" usandovare, em seguida, declare uma variávelidadedo tipo int com valor 28 usando:=. Imprima ambas.✓ Resposta:package main import "fmt" func main() { var nome string = "Maria" idade := 28 fmt.Println(nome, idade) } -
Qual é o valor zero de um slice? E de um ponteiro? Escreva um programa que declare um slice e um ponteiro sem inicializá-los e imprima seus valores.
✓ Resposta:O valor zero de um slice é
nil, e de um ponteiro também énil.package main import "fmt" func main() { var s []int var p *int fmt.Printf("slice: %v\n", s) // slice: [] fmt.Printf("pointer: %v\n", p) // pointer:} -
Declare três variáveis
x,y,zem uma única linha, com valores 10, 20 e 30, respectivamente. Use a sintaxe curta:=.✓ Resposta:package main import "fmt" func main() { x, y, z := 10, 20, 30 fmt.Println(x, y, z) } -
Considere o código abaixo. O que será impresso? Explique o conceito de escopo envolvido.
package main import "fmt" var a = "global" func main() { fmt.Println(a) if true { a := "local" fmt.Println(a) } fmt.Println(a) }✓ Resposta:Será impresso: global, local, global. Dentro do bloco if, a declaração
a := "local"cria uma nova variável local que sombreia a variável globala. Fora do bloco, a variável global permanece inalterada. -
Declare uma variável
contadorno nível do pacote com valor 0. Dentro da função main, incremente-a usandocontador++e imprima o valor. Explique por que isso funciona.✓ Resposta:package main import "fmt" var contador = 0 func main() { contador++ fmt.Println(contador) // 1 }Funciona porque
contadorestá declarada no nível do pacote, portanto é acessível dentro de main. O operador++apenas modifica o valor existente, sem criar uma nova variável.