Variáveis e constantes
As variáveis e constantes são usadas para guardar valores no programa, a diferença principal é que uma variável pode mudar de valor durante a execução, já uma constante não pode mudar depois de definida.
Variáveis
Uma variável é um nome que aponta para um valor.
package main
import "fmt"
func main() {
// Cria uma variável chamada nome.
nome := "Ana"
// Imprime o valor da variável.
fmt.Println(nome)
}
Nesse exemplo, nome guarda o texto "Ana".
Declarando variável com var
Também podemos declarar variáveis usando var.
package main
import "fmt"
func main() {
// Declara uma variável do tipo string.
var nome string = "Ana"
fmt.Println(nome)
}
Essa forma deixa o tipo mais explícito, ela é útil quando o tipo precisa ficar claro ou quando queremos declarar a variável sem valor inicial.
package main
import "fmt"
func main() {
// A variável é criada sem valor inicial.
// Como o tipo é int, ela começa com o valor zero, que é 0.
var idade int
fmt.Println(idade)
}
Alterando o valor de uma variável
Já vimos isso quando falamos sobre := para declarar uma variável e atribuir um valor ao mesmo tempo. Depois que a variável existe, usamos = para mudar o valor.
package main
import "fmt"
func main() {
nome := "Ana"
// A variável já existe.
// Por isso usamos =, não :=.
nome = "Carlos"
fmt.Println(nome)
}
Variável mantém o mesmo tipo
Depois que uma variável tem um tipo, ela continua com aquele tipo, para "mudar", precisamos criar uma nova variável com o novo tipo, é o único jeito.
Declarando várias variáveis
Podemos declarar várias variáveis de uma vez.
package main
import "fmt"
func main() {
// Declara duas variáveis na mesma linha.
nome, idade := "Ana", 20
fmt.Println(nome)
fmt.Println(idade)
}
Também dá para usar var com bloco.
package main
import "fmt"
func main() {
var (
nome string = "Ana"
idade int = 20
ativo bool = true
)
fmt.Println(nome)
fmt.Println(idade)
fmt.Println(ativo)
}
Esse formato aparece quando queremos declarar várias variáveis relacionadas.
Variável declarada precisa ser usada
Como falamos, o Go não permite criar um código e não usar, o mesmo serve para variáveis, se você criar, precisa usar. Isso força o código a ficar mais limpo.
Em exemplos temporários, às vezes usamos _ para ignorar um valor.
package main
func main() {
nome := "Ana"
// O _ diz que estamos ignorando esse valor.
_ = nome
}
O _ é chamado de identificador em branco. Ele serve para descartar valores, mas não deve ser usado para esconder código mal organizado.
Constantes
Uma constante é um valor que não pode ser alterado depois de declarado. Para criar uma constante, usamos const.
package main
import "fmt"
func main() {
// pi é uma constante.
const pi = 3.14
fmt.Println(pi)
}
Depois de criada, a constante não pode receber outro valor.
package main
func main() {
const pi = 3.14
// Erro.
// Constante não pode mudar de valor.
// pi = 3.1415
_ = pi
}
Constante com tipo explícito
Também podemos definir o tipo da constante.
package main
import "fmt"
func main() {
// Constante com tipo explícito.
const nome string = "Ana"
fmt.Println(nome)
}
Quando o tipo não é escrito, o Go mantém a constante de forma mais flexível até ela ser usada.
package main
import "fmt"
func main() {
// Constante sem tipo explícito.
const numero = 10
var a int = numero
var b int64 = numero
var c float64 = numero
fmt.Println(a)
fmt.Println(b)
fmt.Println(c)
}
Esse comportamento é útil, mas não precisa aprofundar demais agora. O ponto importante é que constantes numéricas sem tipo explícito podem se adaptar ao contexto onde são usadas, desde que o valor caiba no tipo.
Constante precisa ser conhecida antes do programa rodar
As constantes são valores conhecidos em tempo de compilação. O tempo de compilação é o momento em que o Go transforma o código em programa executável. Por isso, isso funciona:
package main
import "fmt"
func main() {
// Valor fixo conhecido antes do programa rodar.
const mensagem = "Olá"
fmt.Println(mensagem)
}
Mas isso não funciona:
package main
import "time"
func main() {
// Erro.
// time.Now() só é conhecido quando o programa roda.
// const agora = time.Now()
}
Nesse caso, teria que ser variável:
package main
import (
"fmt"
"time"
)
func main() {
// Variável, porque o valor é gerado durante a execução.
agora := time.Now()
fmt.Println(agora)
}
Constantes com bloco
Assim como var, const também pode ser usado com bloco.
package main
import "fmt"
func main() {
const (
statusAtivo = "ativo"
statusInativo = "inativo"
statusPendente = "pendente"
)
fmt.Println(statusAtivo)
fmt.Println(statusInativo)
fmt.Println(statusPendente)
}
Esse formato é útil quando existem constantes relacionadas.
Entendendo iota
A iota é um contador usado dentro de blocos const. Ele serve para criar sequências de constantes sem precisar escrever todos os valores manualmente.
Exemplo simples:
package main
import "fmt"
func main() {
const (
Segunda = iota
Terca
Quarta
)
fmt.Println(Segunda)
fmt.Println(Terca)
fmt.Println(Quarta)
}
Resultado:
0
1
2
Dentro de um bloco const, o iota começa em 0 e aumenta a cada linha.
Por que iota existe
Sem iota, teríamos que escrever constantes assim:
const (
StatusPendente = 0
StatusAprovado = 1
StatusCancelado = 2
)
Isso funciona, mas é repetitivo, já com iota, podemos escrever:
const (
StatusPendente = iota
StatusAprovado
StatusCancelado
)
O resultado é o mesmo:
StatusPendente -> 0
StatusAprovado -> 1
StatusCancelado -> 2
O iota é útil quando queremos representar opções fixas, como status, tipos, níveis, categorias ou modos de funcionamento.
Ignorando valores com _
Às vezes não queremos usar o valor 0. Nesse caso, podemos ignorar a primeira posição com _.
const (
_ = iota
Janeiro
Fevereiro
Marco
)
Valores:
_ -> 0, ignorado
Janeiro -> 1
Fevereiro -> 2
Marco -> 3
Isso é comum quando o valor 0 não deve representar uma opção válida.
iota reinicia a cada bloco const
O iota só vale dentro do bloco const onde foi usado.
const (
A = iota
B
)
const (
C = iota
D
)
Os valores são:
A -> 0
B -> 1
C -> 0
D -> 1
Cada bloco const começa um novo contador.