Golang básico - Controle de Fluxo - Complemento

Bruno Gomes - May 31 '22 - - Dev Community

Esse post faz parte de uma série onde pretendo compartilhar o básico essencial para desenvolver com GoLang.
Esse em particular é um complemento do Golang básico - Controle de Fluxo

Agora que já vimos como utilizar IF, SWITCH e FOR vamos ver algumas palavras reservadas do Go que são utilizadas para interromper ou acelerar a iteração do código.

continue

A palavra reservada continue é específica para ser utilizada com for, e serve para pular para a próxima iteração:

func main() {
    produtos := []produto{
        {
            nome:   "Produto Final",
            cor:    verde,
            status: publicado,
            criado: time.Now(),
        },
        {
            nome:   "Produto Teste",
            cor:    verde,
            status: rascunho,
            criado: time.Now(),
        },
    }

    for _, p := range produtos {
        if p.status == publicado {
            continue
        }
        fmt.Println(p)
    }
}
Enter fullscreen mode Exit fullscreen mode

Executando esse código verá que somente o Produto Teste é impresso no for.

break

Essa palavra reservada pode ser utilizada em for, switch e select. E ela serve para interromper a iteração do bloco e seguir para próxima instrução do código.

// nesse for nenhum produto será impresso
for _, p := range produtos {
    if p.status == publicado {
        break
    }
    fmt.Println(p)
}
fmt.Println("Loop terminado")
Enter fullscreen mode Exit fullscreen mode
p := produto{
    nome:   "Produto Teste",
    cor:    verde,
    status: rascunho,
    criado: time.Now(),
}
// nenhum case será executado
switch p.status {
case publicado:
    fmt.Println("bloco publicado", p)
case rascunho:
    if p.cor == verde {
        break
    }
    fmt.Println("bloco rascunho", p)
case congelado:
    fmt.Println("bloco congelado", p)
}
fmt.Println("switch terminado")
Enter fullscreen mode Exit fullscreen mode

fallthrough

Essa é específica para ser utilizada com switch, em Go cada case do switch é exclusivo. Diferente de outras linguagens que caso precise ser exclusivo você precisa combinar o case + break.
Mas caso você tenha a necessidade de executar o mesmo case para mais de uma condição, pode fazer uso do fallthrough que transfere o controle para o case seguinte:

// nesse exemplo ambos os cases serão executados
switch p.status {
case rascunho:
    fmt.Println("bloco rascunho")
    fallthrough
case congelado:
    fmt.Println("bloco congelado")
    fmt.Println("aplica lógica compartilhada entre produtos congelados e rascunhos")
}
fmt.Println("switch terminado")
Enter fullscreen mode Exit fullscreen mode

Label com continue e break

Em Go os blocos de códigos podem ter labels e podemos combinar o uso das palavras reservadas de controle com os labels. Isso acaba sendo útil quando temos operações aninhadas. Por exemplo:

func main() {
    produtos := []produto{
        {
            nome:   "Produto Final",
            cor:    verde,
            status: publicado,
            criado: time.Now(),
        },
        {
            nome:   "Produto Teste",
            cor:    verde,
            status: rascunho,
            criado: time.Now(),
        },
    }

    for _, p := range produtos {
        switch p.status {
        case publicado:
            break
        case rascunho:
            fmt.Println("bloco rascunho")
            fallthrough
        case congelado:
            fmt.Println("aplica lógica compartilhada entre produtos congelados e rascunhos")
        }
        fmt.Println("aplica regra para produtos não publicados")
    }
    fmt.Println("Loop terminado")

}
Enter fullscreen mode Exit fullscreen mode

Se você executar o código vai perceber que o break do switch não interrompe a execução do for. Com o uso de label fica assim:

loopDeProduto:
    for _, p := range produtos {
        switch p.status {
        case publicado:
            break loopDeProduto
        case rascunho:
            fmt.Println("bloco rascunho")
            fallthrough
        case congelado:
            fmt.Println("aplica lógica compartilhada entre produtos congelados e rascunhos")
        }
        fmt.Println("aplica regra para produtos não publicados")
    }
    fmt.Println("Loop terminado")
Enter fullscreen mode Exit fullscreen mode

Ou seja, com label você consegue controlar a iteração do for de dentro do switch. Mas poderia ser dois for aninhados também, ou qualquer outro bloco aninhado.

Bom esses recursos de controle são importantes de saber que existem, porém na minha opinião eles são bem evitáveis.
No geral quando você está fazendo operações aninhadas e precisando fazer um controle tão detalhado é um grande sinal de que talvez o seu código não esteja tão simples.
Sempre considere a expressividade do código, não o faça funcionar a qualquer custo!

Resumo

  • continue pula para próxima execução do for.
  • break interrompe execução do bloco.
  • fallthrough transfere controle para o case seguinte.
  • Labels te possibilitam controlar de blocos aninhados.
  • Sempre considere a expressividade do seu código.
. . . . . . . .