// ============================================
// GO AVANÇADO: PADRÕES DE CONTROLE
// ============================================
// Guia completo sobre padrões de controle de fluxo,
// desde instruções básicas até estratégias avançadas
// de tratamento de condições e erros
// ============================================
// SUMÁRIO COMPLETO
// ============================================
// CONDICIONAIS BÁSICOS
// 1. if/else simples
// 2. Inicialização na condição
// 3. Múltiplas condições
// 4. Switch simples
// 5. Switch com type assertion
//
// LOOPS
// 6. for simples
// 7. for range
// 8. for range com índice
// 9. break e continue
// 10. labeled loops
//
// PADRÕES DEFENSIVOS
// 11. Guard clauses
// 12. Early returns
// 13. Validação em entrada
// 14. Padrão de erro
// 15. Panic e recover
//
// PADRÕES AVANÇADOS
// 16. Type switches
// 17. Type assertions
// 18. Switch com expressões complexas
// 19. Padrões com defer
// 20. Control flow com channels
package main
import (
"errors"
"fmt"
"log"
"strconv"
"strings"
)
// ============================================
// 1. IF/ELSE SIMPLES
// ============================================
func exemplo_if_else_simples() {
idade := 25
// if simples
if idade >= 18 {
[Link]("Você é maior de idade")
}
// if/else
if idade >= 65 {
[Link]("Você é idoso")
} else if idade >= 18 {
[Link]("Você é adulto")
} else {
[Link]("Você é menor de idade")
}
// Condição com operadores lógicos
if idade >= 18 && idade < 65 {
[Link]("Você está na força de trabalho")
}
// Operador ternário não existe em Go
// Mas pode usar if inline (não recomendado para valores)
status := "menor"
if idade >= 18 {
status = "maior"
}
[Link]("Status:", status)
}
// ============================================
// 2. INICIALIZAÇÃO NA CONDIÇÃO
// ============================================
// Padrão muito usado em Go: inicializar variável na condição
func converter_numero(s string) {
// Inicializar err dentro do if
if numero, err := [Link](s); err != nil {
[Link]("Erro na conversão:", err)
} else {
[Link]("Número convertido:", numero*2)
}
// A variável 'numero' não existe aqui (escopo limitado)
// [Link](numero) // erro de compilação
// Padrão comum: verificar erro imediatamente
dados := []byte("123")
if valor, err := [Link](string(dados)); err == nil {
[Link]("Valor válido:", valor)
}
}
// ============================================
// 3. MÚLTIPLAS CONDIÇÕES
// ============================================
func verificar_credenciais(usuario, senha string, tentativas int) bool {
// Múltiplas condições AND
if usuario != "" && senha != "" && len(senha) >= 6 {
[Link]("Credenciais básicas OK")
return true
}
// Múltiplas condições OR
if usuario == "admin" || usuario == "root" {
[Link]("Usuário privilegiado")
}
// Expressões complexas com parênteses
if (usuario == "admin" && tentativas < 3) || (usuario != "admin" &&
tentativas < 5) {
[Link]("Pode tentar novamente")
}
return false
}
func exemplo_multiplas_condicoes() {
verificar_credenciais("joao", "senha123", 1)
verificar_credenciais("admin", "pass", 2)
}
// ============================================
// 4. SWITCH SIMPLES
// ============================================
func descrever_dia(dia int) {
// Switch simples
switch dia {
case 1:
[Link]("Segunda-feira")
case 2:
[Link]("Terça-feira")
case 3:
[Link]("Quarta-feira")
case 4, 5: // múltiplos valores
[Link]("Quinta ou Sexta")
case 6, 7:
[Link]("Fim de semana")
default:
[Link]("Dia inválido")
}
// Switch com expressão
resultado := 10
switch resultado {
case 0:
[Link]("Nenhum resultado")
case 1, 2, 3:
[Link]("Poucos resultados")
default:
[Link]("Muitos resultados")
}
// Switch sem expressão (como if/else if)
status := "ativo"
switch {
case status == "ativo":
[Link]("Sistema funcionando")
case status == "inativo":
[Link]("Sistema parado")
default:
[Link]("Status desconhecido")
}
}
// ============================================
// 5. SWITCH COM TYPE ASSERTION
// ============================================
func processar_dado(dado interface{}) {
// Type switch
switch v := dado.(type) {
case int:
[Link]("É inteiro:", v*2)
case string:
[Link]("É string:", [Link](v))
case []int:
[Link]("É slice de ints:", len(v))
case map[string]interface{}:
[Link]("É mapa:", v)
case nil:
[Link]("É nil")
default:
[Link]("Tipo desconhecido")
}
}
func exemplo_type_switch() {
processar_dado(42)
processar_dado("olá")
processar_dado([]int{1, 2, 3})
processar_dado(map[string]interface{}{"chave": "valor"})
processar_dado(nil)
}
// ============================================
// 6. FOR SIMPLES
// ============================================
func exemplo_for_simples() {
// for clássico (tipo C)
for i := 0; i < 5; i++ {
[Link](i, " ")
}
[Link]()
// for com múltiplas variáveis
for i, j := 0, 10; i < 5; i, j = i+1, j-1 {
[Link]("i=%d, j=%d\n", i, j)
}
// for infinito (com break)
contador := 0
for {
[Link]("Loop infinito:", contador)
contador++
if contador >= 3 {
break
}
}
// for com only condition (tipo while)
i := 0
for i < 3 {
[Link]("While loop:", i)
i++
}
}
// ============================================
// 7-8. FOR RANGE
// ============================================
func exemplo_for_range() {
// Range sobre slice (valor apenas)
numeros := []int{10, 20, 30}
for valor := range numeros {
[Link]("Índice:", valor)
}
// Range sobre slice (índice e valor)
for indice, valor := range numeros {
[Link]("[%d]=%d ", indice, valor)
}
[Link]()
// Range sobre string
texto := "Olá"
for indice, runa := range texto {
[Link]("Índice %d: %c\n", indice, runa)
}
// Range sobre map
pessoa := map[string]int{"Alice": 30, "Bob": 25}
for chave, valor := range pessoa {
[Link]("%s: %d anos\n", chave, valor)
}
// Range sobre channel (recepciona valores até fechar)
ch := make(chan int, 3)
ch <- 1
ch <- 2
ch <- 3
close(ch)
for valor := range ch {
[Link]("Do canal:", valor)
}
// Ignorar índice com _
for _, v := range numeros {
[Link](v, " ")
}
[Link]()
// Ignorar valor
for i := range numeros {
[Link](i, " ")
}
[Link]()
}
// ============================================
// 9. BREAK E CONTINUE
// ============================================
func exemplo_break_continue() {
[Link]("Exemplo com break:")
for i := 0; i < 10; i++ {
if i == 5 {
[Link]("Saindo no 5")
break
}
[Link](i, " ")
}
[Link]()
[Link]("\nExemplo com continue:")
for i := 0; i < 5; i++ {
if i == 2 {
[Link]("Pulando 2")
continue
}
[Link](i, " ")
}
[Link]()
// Break em loops aninhados
[Link]("\nBreak em loops aninhados:")
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
[Link]("Saindo quando i=1, j=1")
break // apenas o loop interno
}
[Link]("(%d,%d) ", i, j)
}
[Link]()
}
}
// ============================================
// 10. LABELED LOOPS
// ============================================
func exemplo_labeled_loops() {
// Labels permitem break/continue em loops externos
OUTER:
for i := 0; i < 3; i++ {
for j := 0; j < 3; j++ {
if i == 1 && j == 1 {
[Link]("Break para OUTER")
break OUTER // sai do loop externo
}
[Link]("(%d,%d) ", i, j)
}
[Link]()
}
[Link]("Saiu de ambos os loops")
}
// ============================================
// 11. GUARD CLAUSES
// ============================================
// Guard clause: verificar erro no início e retornar cedo
// Reduz a indentação e torna o código mais legível
func processar_pedido_ruim(id int) {
// Ruim: muita indentação
if id > 0 {
[Link]("ID válido")
// resto do código altamente indentado
if id < 1000 {
[Link]("ID está no intervalo")
}
}
}
func processar_pedido_bom(id int) {
// Bom: usar guard clauses
// Verificar e retornar cedo se inválido
if id <= 0 {
[Link]("Erro: ID deve ser positivo")
return
}
if id >= 1000 {
[Link]("Erro: ID muito grande")
return
}
// Código principal sem indentação extra
[Link]("Processando pedido:", id)
}
// ============================================
// 12. EARLY RETURNS
// ============================================
// Early return ajuda a tratar casos especiais primeiro
func buscar_usuario(id int) (string, error) {
// Verificar pré-condições no início
if id <= 0 {
return "", [Link]("ID inválido")
}
usuarios := map[int]string{
1: "Alice",
2: "Bob",
3: "Carol",
}
// Early return se não encontrado
nome, existe := usuarios[id]
if !existe {
return "", [Link]("usuário não encontrado")
}
// Agora sabemos que temos um usuário válido
return nome, nil
}
func exemplo_early_returns() {
for _, id := range []int{0, 1, 2, 999} {
nome, err := buscar_usuario(id)
if err != nil {
[Link]("Erro:", err)
continue
}
[Link]("Usuário encontrado:", nome)
}
}
// ============================================
// 13. VALIDAÇÃO EM ENTRADA
// ============================================
type Pedido struct {
ID int
Produto string
Quantidade int
Preco float64
}
func validar_pedido(p *Pedido) error {
// Validar nulo
if p == nil {
return [Link]("pedido não pode ser nulo")
}
// Validar cada campo
if [Link] <= 0 {
return [Link]("ID deve ser positivo")
}
if [Link] == "" {
return [Link]("produto é obrigatório")
}
if [Link] <= 0 {
return [Link]("quantidade deve ser positiva")
}
if [Link] < 0 {
return [Link]("preço não pode ser negativo")
}
return nil
}
func criar_pedido(p *Pedido) error {
// Validar imediatamente
if err := validar_pedido(p); err != nil {
return [Link]("validação falhou: %w", err)
}
// Prosseguir com confiança
[Link]("Pedido válido: %d x %s\n", [Link], [Link])
return nil
}
func exemplo_validacao_entrada() {
pedidos := []*Pedido{
{ID: 1, Produto: "Notebook", Quantidade: 2, Preco: 3000},
{ID: 0, Produto: "Mouse", Quantidade: 5, Preco: 50}, // ID inválido
{ID: 3, Produto: "", Quantidade: 10, Preco: 100}, // produto
vazio
{ID: 4, Produto: "Teclado", Quantidade: -1, Preco: 200}, // qtd
negativa
}
for _, p := range pedidos {
if err := criar_pedido(p); err != nil {
[Link]("Erro:", err)
}
}
}
// ============================================
// 14. PADRÃO DE ERRO (ERROR WRAPPING)
// ============================================
// Erro customizado para contexto
type ErroNegocio struct {
Mensagem string
Codigo int
Causa error
}
func (e *ErroNegocio) Error() string {
return [Link]("[%d] %s: %v", [Link], [Link], [Link])
}
func buscar_dados_com_retry(tentativas int) error {
// Simular falha
err := [Link]("conexão recusada")
if tentativas <= 0 {
// Envolver o erro com contexto
return &ErroNegocio{
Mensagem: "Falha na busca de dados",
Codigo: 500,
Causa: err,
}
}
return nil
}
func exemplo_error_wrapping() {
err := buscar_dados_com_retry(0)
if err != nil {
[Link]("Erro estruturado:", err)
// Verificar tipo do erro
if erroNeg, ok := err.(*ErroNegocio); ok {
[Link]("Código de erro: %d\n", [Link])
}
}
}
// ============================================
// 15. PANIC E RECOVER
// ============================================
// Panic e recover para situações excepcionais
func funcao_perigosa(valor int) {
if valor < 0 {
panic("Valor não pode ser negativo!")
}
[Link]("Processando:", valor)
}
func executar_com_seguranca(valor int) {
defer func() {
// Recover captura o panic
if r := recover(); r != nil {
[Link]("Recuperado de panic:", r)
}
}()
funcao_perigosa(valor)
}
func exemplo_panic_recover() {
executar_com_seguranca(10) // OK
executar_com_seguranca(-5) // Panic, mas recuperado
[Link]("Programa continua após recover")
}
// ============================================
// 16. TYPE ASSERTIONS SEGURAS
// ============================================
func exemplo_type_assertions() {
var valor interface{} = "texto"
// Type assertion sem segurança (panic se falhar)
// str := valor.(string) // OK
// num := valor.(int) // PANIC!
// Type assertion segura
if str, ok := valor.(string); ok {
[Link]("É string:", str)
} else {
[Link]("Não é string")
}
// Type assertion com tipos múltiplos
valores := []interface{}{42, "olá", 3.14, true}
for _, v := range valores {
switch val := v.(type) {
case int:
[Link]("%d é int\n", val)
case string:
[Link]("%s é string\n", val)
case float64:
[Link]("%f é float64\n", val)
case bool:
[Link]("%v é bool\n", val)
}
}
}
// ============================================
// 17. SWITCH COM EXPRESSÕES COMPLEXAS
// ============================================
func classificar_idade(idade int) {
switch {
case idade < 0:
[Link]("Erro: idade negativa")
case idade < 13:
[Link]("Criança")
case idade < 18:
[Link]("Adolescente")
case idade < 65:
[Link]("Adulto")
case idade >= 65:
[Link]("Idoso")
}
}
func classificar_temperatura(celsius float64) {
switch {
case celsius < -10:
[Link]("Muito frio")
case celsius >= -10 && celsius < 0:
[Link]("Frio")
case celsius >= 0 && celsius < 15:
[Link]("Fresco")
case celsius >= 15 && celsius < 25:
[Link]("Temperado")
case celsius >= 25:
[Link]("Quente")
}
}
func exemplo_switch_complexo() {
classificar_idade(8)
classificar_idade(15)
classificar_idade(35)
classificar_idade(70)
[Link]()
classificar_temperatura(-15)
classificar_temperatura(10)
classificar_temperatura(20)
classificar_temperatura(30)
}
// ============================================
// 18. PADRÕES COM DEFER
// ============================================
func exemplo_defer_controle() {
[Link]("Início")
// Defer agenda execução para o final da função
defer func() {
[Link]("Limpeza 2")
}()
defer func() {
[Link]("Limpeza 1")
}()
// Defers são executados em LIFO (Last In, First Out)
[Link]("Processamento")
[Link]("Fim")
// Saída: Início, Processamento, Fim, Limpeza 1, Limpeza 2
}
// Defer é excelente para limpeza de recursos
func exemplificar_limpeza() {
// Simular arquivo
tipo_recurso := "arquivo"
defer func() {
[Link]("Fechando %s\n", tipo_recurso)
}()
[Link]("Abrindo %s\n", tipo_recurso)
// Even com erros, defer executa
if false {
return // defer ainda executa
}
[Link]("Usando %s\n", tipo_recurso)
}
// ============================================
// 19. LOOPS COM CONTROLE AVANÇADO
// ============================================
func exemplo_loops_avancados() {
// Loop com acumulação
soma := 0
for i := 1; i <= 5; i++ {
soma += i
if soma > 6 {
[Link]("Parando em", i)
break
}
}
[Link]("Soma final:", soma)
// Loop com transformação
[Link]("\nTransformação:")
for i := 1; i <= 5; i++ {
if i%2 == 0 {
continue // pular pares
}
[Link](i, " ")
}
[Link]()
// Loop com estado
[Link]("\nLoop com estado:")
produtos := []string{"A", "B", "C", "D"}
for i, p := range produtos {
if i > 0 && i%2 == 0 {
[Link]()
}
[Link](p, " ")
}
[Link]()
}
// ============================================
// MAIN FUNCTION
// ============================================
func main() {
[Link]("=== Padrões de Controle em Go ===\n")
[Link]("--- If/Else Simples ---")
exemplo_if_else_simples()
[Link]("\n--- Inicialização na Condição ---")
converter_numero("456")
[Link]("\n--- Múltiplas Condições ---")
exemplo_multiplas_condicoes()
[Link]("\n--- Switch Simples ---")
descrever_dia(4)
[Link]("\n--- Type Switch ---")
exemplo_type_switch()
[Link]("\n--- For Simples ---")
exemplo_for_simples()
[Link]("\n--- For Range ---")
exemplo_for_range()
[Link]("\n--- Break e Continue ---")
exemplo_break_continue()
[Link]("\n--- Labeled Loops ---")
exemplo_labeled_loops()
[Link]("\n--- Guard Clauses ---")
processar_pedido_bom(500)
[Link]("\n--- Early Returns ---")
exemplo_early_returns()
[Link]("\n--- Validação em Entrada ---")
exemplo_validacao_entrada()
[Link]("\n--- Error Wrapping ---")
exemplo_error_wrapping()
[Link]("\n--- Panic e Recover ---")
exemplo_panic_recover()
[Link]("\n--- Type Assertions ---")
exemplo_type_assertions()
[Link]("\n--- Switch Complexo ---")
exemplo_switch_complexo()
[Link]("\n--- Defer para Controle ---")
exemplo_defer_controle()
[Link]("\n--- Exemplificar Limpeza com Defer ---")
exemplificar_limpeza()
[Link]("\n--- Loops Avançados ---")
exemplo_loops_avancados()
}