if com Inicialização e Padrões de switch
O Go aprimora o código condicional permitindo que if e switch executem uma instrução de inicialização única antes do branch, e oferecendo switches de valor e switches de tipo em interfaces.
Busque em todas as páginas da documentação
O Go aprimora o código condicional permitindo que if e switch executem uma instrução de inicialização única antes do branch, e oferecendo switches de valor e switches de tipo em interfaces.
Dominar essas formas mantém o tratamento de erros plano e substitui longas cadeias de if/else por discriminação mais clara.
Uma instrução de inicialização em if ou switch escopa variáveis temporárias para o bloco.
Switches de expressão comparam um valor contra casos sem fallthrough implícito.
Switches sem tag encadeiam casos booleanos como else if.
Switches de tipo inspecionam tipos dinâmicos dentro de interfaces.
fallthrough é explícito e incomum.
Cartão de receita de referência rápida - pronto para copiar e colar.
package main
import (
"fmt"
"os"
)
func main() {
// Abre um arquivo e trata o erro imediatamente.
if f, err := os.Open("config.txt"); err != nil {
fmt.Println(err)
return
} else {
// Garante que o arquivo seja fechado quando a função retornar.
defer f.Close()
fmt.Println("aberto", f.Name())
}
code := 404
// Switch de valor compara 'code' com constantes.
switch code {
case 200:
fmt.Println("ok")
case 404:
fmt.Println("não encontrado")
default:
fmt.Println("outro")
}
}Quando usar isso:
if err := ...; err != nil imediatamente após chamadas que retornam erros.switch de valor ao comparar uma expressão com muitas constantes.switch true sem tag (ou condições nuas) para casos booleanos ordenados.interface{} ou restrição genérica.package main
import (
"encoding/json"
"fmt"
)
// Event representa um evento com um tipo e um payload.
type Event struct {
Kind string
Payload any
}
// handle processa um evento com base no tipo de seu payload.
func handle(e Event) error {
// Type switch para inspecionar o tipo dinâmico do payload.
switch p := e.Payload.(type) {
case nil:
return fmt.Errorf("payload ausente para %s", e.Kind)
case json.RawMessage:
fmt.Println("bytes json brutos", len(p))
case map[string]any:
fmt.Println("chaves do objeto", len(p))
case string:
fmt.Println("string", p)
default:
// Lida com tipos de payload inesperados.
return fmt.Errorf("payload não suportado %T", p)
}
return nil
}
// classify retorna uma letra de nota com base em uma pontuação.
func classify(score int) string {
// Switch sem tag encadeia condições booleanas.
switch {
case score >= 90:
return "A"
case score >= 80:
return "B"
default:
return "C"
}
}
func main() {
events := []Event{
{Kind: "text", Payload: "hello"},
{Kind: "obj", Payload: map[string]any{"k": 1}},
}
for _, e := range events {
// Verifica erros após cada chamada de handle.
if err := handle(e); err != nil {
fmt.Println(err)
}
}
fmt.Println(classify(85))
}O que isso demonstra:
p := e.Payload.(type) vincula uma variável tipada por caso.default lida com tipos dinâmicos inesperados com %T em erros.if/else if.if/switch.fallthrough apareça.switch pode incluir uma instrução de inicialização: switch err := f(); err != nil { case ... } (incomum, mas válido).| Forma | Sintaxe | Corresponde em |
|---|---|---|
| Valor | switch x { case v: | igualdade em x comparável |
| Sem Tag | switch { case cond: | booleano cond |
| Tipo | switch v := i.(type) { case T: | tipo dinâmico da interface i |
| Com init | switch x := f(); x { | valor de x após init |
fallthrough| Regra | Comportamento |
|---|---|
| Padrão | Pare após o primeiro caso correspondente |
fallthrough | Continue para o próximo caso incondicionalmente |
| Último caso | fallthrough para default permitido, mas raro |
// Type assert com vírgula-ok no if - alternativa ao type switch para um tipo
if s, ok := v.(string); ok {
fmt.Println(s)
}
// switch em strings com casos duplicados é um erro de compilação
// correspondência insensível a maiúsculas/minúsculas: normalize antes do switch ou use switch sem tagerr após o bloco if quando declarado na inicialização. Correção: mantenha o tratamento dentro do bloco ou declare err fora intencionalmente.break (bugs do C) não se aplica, mas fallthrough acidental causa execução dupla. Correção: remova fallthrough, a menos que seja deliberado.x.(type) só funciona em operandos de interface. Correção: passe any ou um pequeno wrapper de interface.switch v := i.(type) { case *T: } pode corresponder a um ponteiro nil tipado. Correção: verifique v == nil dentro do caso.case 1, 2:.| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
Cadeia if/else | Poucos branches com condições não relacionadas | Muitas constantes em um valor |
Pesquisa em mapa handlers[key] | Tabela de despacho para strings | Precisa de verificações de exaustividade de compilação |
Type assertion v.(T) | Tipo único conhecido | Muitos tipos para discriminar |
| Genéricos + restrições | Conjuntos de tipos em tempo de compilação | Blobs JSON heterogêneos em tempo de execução |
errors.Is / errors.As | Inspeção de cadeia de erros | Valores de interface não-erro |
Mantém a variável de erro escopada para a verificação.
Os leitores veem a aquisição e a validação juntas.
Quase nunca em código de aplicação.
Prefira chamadas de helper compartilhadas de múltiplos casos em vez disso.
Os casos devem ser constantes comparáveis em tempo de compilação ou expressões booleanas (forma sem tag).
Você não pode usar switch em um slice diretamente - use padrões de índice ou comprimento em vez disso.
Type switches lidam com muitos tipos em uma única construção.
Type assertion v.(T) visa um único tipo e retorna ok.
Para interfaces, o valor dinâmico pode ser copiado dependendo do tipo.
Valores grandes - use switch em ponteiro ou índice em vez disso.
Sim - compare com errors.Is em casos sem tag:
case errors.Is(err, os.ErrNotExist):
Uma grafia mais antiga de switch sem tag.
switch { case cond: é a forma moderna idiomática.
Sim - if a, err := f(); err != nil funciona como uma declaração de variável curta.
Pelo menos um nome deve ser novo em alguns contextos com regras de reutilização de :=.
Sim, mas inúteis - geralmente um sinal para excluir ou adicionar tratamento.
Linters podem sinalizar casos vazios.
Trate runes como inteiros com constantes de caractere:
case '+', '-':
if e switchifif estilo initVersões de Stack: Esta página foi escrita para Go 1.26.x (padrão Green Tea GC, go fix modernizers - verifique o patch na compilação), chi (última - verifique na compilação), gin (última - verifique na compilação), echo (última - verifique na compilação), google.golang.org/grpc (última - verifique na compilação), sigs.k8s.io/controller-runtime (última - verifique na compilação), kubebuilder (última - verifique na compilação), tinygo (última - verifique os alvos de placa na compilação), wazero (última - verifique na compilação), e golangci-lint (última - verifique o conjunto de linters na compilação).
Revisado por Chris St. John·Última atualização: 18 de jul. de 2026