O if do Go não tem parênteses em volta da condição, sempre exige chaves e pode começar com uma instrução curta que declara variáveis com escopo restrito ao if.
As condições são avaliadas de cima para baixo e o primeiro ramo verdadeiro é executado. else if e else são opcionais.
Regras de sintaxe
Três regras diferem de C, Java e JavaScript:
- Sem parênteses em volta da condição.
if (x > 5)compila, mas ogofmtremove os parênteses. - Chaves são obrigatórias, mesmo para uma única instrução. Não existe
if x > 5 returnsem chaves. - O
elsefica na mesma linha da chave de fechamento. Go insere um ponto e vírgula depois de uma}no fim da linha, então isto falha:
if x > 5 {
fmt.Println("big")
}
else {
fmt.Println("small")
}
syntax error: unexpected keyword else, expected }
Escreva } else { em uma linha só.
A condição precisa ser um bool. Go não trata 0, "" ou nil como falso, então if count {} e if name {} não compilam. Compare de forma explícita: if count > 0, if name != "", if user != nil.
Combine condições com && (e), || (ou) e ! (não). && e || fazem curto-circuito, o que torna as verificações de nil seguras:
if user != nil && user.IsAdmin() {
// user.IsAdmin() is only called when user is not nil
}
if com instrução de inicialização
Um if pode executar uma instrução curta antes da condição, separada por ponto e vírgula. As variáveis declaradas nela ficam visíveis em todos os ramos daquele if, e em nenhum lugar depois:
O padrão mantém variáveis de vida curta fora do escopo ao redor. Ele aparece o tempo todo com buscas em map (v, ok := m[k]), type assertions (s, ok := v.(string)) e erros.
O outro lado: se você precisa do valor depois do if, declare-o antes. Um erro comum é colocar um resultado na instrução de inicialização e depois tentar usá-lo mais abaixo.
O idioma if err != nil
Funções que podem falhar devolvem um error por último. Verifique na hora, trate ou devolva o erro e siga com o caminho feliz sem indentação:
Repare que não há else depois de if err != nil { return ... }. O estilo Go trata o erro, retorna e deixa o fluxo normal na margem esquerda. A página de tratamento de erros cobre o empacotamento e a verificação de tipos de erro.
Retornos antecipados em vez de aninhamento
Blocos if muito aninhados são difíceis de ler. Inverta as condições e retorne cedo; cada verificação passa a funcionar como uma guarda:
// Nested
func canCheckout(u *User, cart *Cart) bool {
if u != nil {
if u.Verified {
if len(cart.Items) > 0 {
return true
}
}
}
return false
}
// Guards
func canCheckout(u *User, cart *Cart) bool {
if u == nil || !u.Verified {
return false
}
if len(cart.Items) == 0 {
return false
}
return true
}
Programadores Go chamam isso de manter o caminho feliz alinhado à esquerda. Linters como o revive apontam um else depois de um bloco que termina em return, porque o else acrescenta indentação sem motivo.
if/else ou switch
Uma cadeia longa de else if que testa um valor contra vários casos fica mais legível como switch. Um switch sem expressão substitui uma cadeia if/else if de condições quaisquer:
switch {
case score >= 90:
return "A"
case score >= 80:
return "B"
default:
return "F"
}
Use if para um ou dois ramos, e switch a partir de três.
Sem operador ternário
Go não tem cond ? a : b. Atribua com if:
label := "odd"
if n%2 == 0 {
label = "even"
}
A página do operador ternário explica o porquê e mostra as alternativas.
Erros comuns
- Shadowing com :=.
if x, err := f(); err == nil { ... }declara umxnovo só para oif. Umxde fora não é atualizado. - Atribuição na condição.
if x = 5 {}é erro de compilação (cannot use assignment x = 5 as value), e não um bug silencioso como em C. Use==. - Comparar floats com ==.
if total == 0.3falha para valores calculados. Compare com uma tolerância. - Verificar o erro errado. Depois de
a, err := f()eb, err := g(), confira se cadaif err != nilestá logo depois da sua chamada.
Perguntas frequentes
Como escrever if else em Go?
Sem parênteses em volta da condição, e com chaves sempre obrigatórias:
if x > 10 {
fmt.Println("big")
} else if x > 5 {
fmt.Println("medium")
} else {
fmt.Println("small")
}
O else precisa ficar na mesma linha da chave de fechamento do bloco anterior.
O que é um if com instrução de inicialização em Go?
Uma instrução curta antes da condição, separada por ponto e vírgula: if n, err := strconv.Atoi(s); err != nil { ... }. As variáveis declaradas ali só existem dentro do if e dos seus ramos else if e else, o que evita que vazem para o resto da função.
Dá para escrever um if em uma linha em Go?
Não sem chaves. if ok return e if (ok) x = 1; são erros de sintaxe. A forma mais curta é if ok { return }, e o gofmt coloca o corpo em uma linha própria. Go também não tem operador ternário, então um valor condicional exige um if/else ou uma pequena função auxiliar.
Por que Go usa if err != nil em todo lugar?
Go não tem exceções. Funções que podem falhar devolvem um error como último resultado, e quem chama verifica na hora com if err != nil. A repetição é o preço de ter cada ponto de falha visível onde acontece.