Break em Go: como funciona em switch e select? Guia completo

Treinador Online de Python para Iniciantes

Aprenda Python facilmente sem sobrecarga teórica. Resolva tarefas práticas com verificação automática e escreva código diretamente no navegador.

Start Course

Break que confunde: como o Go virou a regra do "switch" de cabeça para baixo

\n\n

Se você já programou em C, C++, Java ou JavaScript, conhece o ritual: após cada case em um switch, é obrigatório colocar um break. Caso contrário, bem-vindo ao inferno do "fall-through", onde o código executa de um case para o outro até encontrar um break ou o fim da estrutura.

\n\n

Agora imagine: você migra para o Go, escreve um switch e, por hábito, insere break no final de cada case. O código funciona. Mas você se pergunta: "Será que ele é necessário? E o que acontece se eu o remover?".

\n\n

Essa é uma das perguntas mais populares no Stack Overflow sobre Go. E a resposta surpreende os iniciantes: no Go, o break em switch e select não é obrigatório, mas ele existe e faz algo diferente. Vamos entender com exemplos para você nunca mais se confundir.

\n\n

Go vs. C: o switch "invertido"

\n\n

Nas linguagens clássicas derivadas de C, o switch funciona assim:

\n\n
// Pseudocódigo C\nint x = 2;\nswitch(x) {\n    case 1:\n        printf("Um");\n        break;  // Sem break, vai para o próximo case\n    case 2:\n        printf("Dois");\n        break;\n    default:\n        printf("Outro");\n}\n// Saída: "Dois"
\n\n

Remova o break após case 1 — e o programa imprimirá "UmDois". Esse comportamento é chamado de fall-through e frequentemente causa bugs.

\n\n

No Go, decidiram: "Chega disso!" Por padrão, cada case em um switch termina automaticamente, e o break não é necessário:

\n\n
package main\n\nimport "fmt"\n\nfunc main() {\n    x := 2\n    switch x {\n    case 1:\n        fmt.Println("Um")\n        // break não é necessário — sairemos do switch\n    case 2:\n        fmt.Println("Dois")\n        // break não é necessário\n    default:\n        fmt.Println("Outro")\n    }\n    // Saída: "Dois"\n}
\n\n

Mas se você ainda assim colocar um break — tudo bem, o código apenas sairá do switch mais cedo. No entanto, por que adicionar um break desnecessário se esse é o comportamento padrão?.

\n\n

E o fall-through?

\n\n

Se você precisar "cair" para o próximo case, o Go oferece uma palavra-chave explícita — fallthrough:

\n\n
switch x {\ncase 1:\n    fmt.Println("Um")\n    fallthrough  // Explicitamente: "Quero ir para o próximo case"\ncase 2:\n    fmt.Println("Dois")\ndefault:\n    fmt.Println("Outro")\n}\n// Com x=1, a saída será: "Um" e "Dois"
\n\n

Observe: fallthrough funciona apenas para o próximo case, não em cadeia. Isso foi feito propositalmente para evitar erros acidentais.

\n\n

Select: o "irmão" multicanal do switch

\n\n

O Go tem uma construção única — o select. Ele é semelhante ao switch, mas funciona apenas com canais. E aqui o break também existe, mas com um truque.

\n\n
package main\n\nimport (\n    "fmt"\n    "time"\n)\n\nfunc main() {\n    ch1 := make(chan string)\n    ch2 := make(chan string)\n\n    go func() {\n        time.Sleep(1 * time.Second)\n        ch1 <- "Olá do canal 1"\n    }()\n    go func() {\n        time.Sleep(2 * time.Second)\n        ch2 <- "Olá do canal 2"\n    }()\n\n    select {\n    case msg1 := <-ch1:\n        fmt.Println(msg1)\n        break  // Sai do select\n    case msg2 := <-ch2:\n        fmt.Println(msg2)\n        break  // Sai do select\n    case <-time.After(3 * time.Second):\n        fmt.Println("Timeout")\n    }\n}
\n\n

Aqui, o break também não é obrigatório — o select termina após executar um case. Mas para que ele serve?. A resposta: para sair de um loop externo!

\n\n

A principal "sacada" do break

Blogs

Book Recommendations