web-dev-qa-db-fra.com

Comment sortir des boucles imbriquées dans Golang?

J'ai une boucle externe et une boucle interne, chacune parcourant une plage. Je souhaite quitter la boucle externe lorsqu'une condition est remplie à l'intérieur de la boucle interne.

J'ai une solution qui fonctionne en utilisant deux "pause", une dans la boucle interne et une dans la boucle externe, juste en dehors de la boucle interne. Voici le (cas très simplifié de démonstration):

package main

import (
    "fmt"
)

func main() {

    Word := ""
    for _, i := range("ABCDE") {
        for _,j := range("ABCDE") {
            Word = string(i) + string(j)
            fmt.Println(Word)
            if Word == "DC" {
                break
            }
        }
        if Word == "DC" {
            break
        }
    }
    // More logic here that needs to be executed
}

Il n’ya pas de problème avec cette solution, mais elle m’apparaît patché et laide. Y a-t-il une meilleure manière de faire cela?

Je peux essayer d’avoir une autre boucle conditionnelle en dehors de la boucle extérieure dans la solution précédente et d’avoir une étiquette et d’utiliser continuer avec l’étiquette, like so . Mais comme vous pouvez le constater, cette approche n’est pas plus élégante que la solution avec pause.

package main

import (
    "fmt"
)

func main() {

    Word := ""

Exit:
    for Word != "DC" {
        for _, i := range "ABCDE" {
            for _, j := range "ABCDE" {
                Word = string(i) + string(j)
                fmt.Println(Word)
                if Word == "DC" {
                    continue Exit
                }
            }
        }
    }
    // More logic here that needs to be executed
}

J'ai vu des questions similaires concernant d'autres langages (C, C #, Python, etc.). Mais ce qui m'intéresse vraiment, c'est de savoir s'il existe un truc avec les constructions de golang telles que 'for select'.

5
Jayachandran

utiliser la fonction

package main

import (
    "fmt"
)

func getWord() string {
    Word := ""
    for Word != "DC" {
        for _, i := range "ABCDE" {
            for _, j := range "ABCDE" {
                Word = string(i) + string(j)
                fmt.Println(Word)
                if Word == "DC" {
                    return Word
                }
            }
        }
    }
}

func main(){
    Word := getWord()
}

Edit: merci à @peterSO qui pointe des erreurs dans les détails et fournit ce terrain de jeu https://play.golang.org/p/udcJptBW9pQ

5
kkesley

Pourquoi pas goto?

package main

import (
    "fmt"
)

func main() {

    Word := ""

        for _, i := range "ABCDE" {
            for _, j := range "ABCDE" {
                Word = string(i) + string(j)
                fmt.Println(Word)
                if Word == "DC" {
                    goto Exit
                }
            }
        }
    Exit: // More logic here that needs to be executed
}
5
aultimus

Le plus simple semble être quelque chose comme:

func main() {
    Word := ""
    isDone := false
    for _, i := range("ABCDE") {
        for _,j := range("ABCDE") {
            Word = string(i) + string(j)
            fmt.Println(Word)
            isDone = Word == "DC"
            if isDone {
                break
            }
        }
        if isDone {
            break
        }
    }
    //  other stuff
}

Une alternative utilisant un générateur

Cependant, vous pouvez également utiliser un générateur pour créer la séquence de mots comme dans:

func makegen () chan string {
    c:= make(chan string)
    go func () {
        for _, i := range ("ABCDE") {
            for _, j := range ("ABCDE") {
                c <- string(i) + string(j)
            }
        }
        close (c)
    }()

    return c
}


func main() {
    Word := ""
    for Word = range makegen() {
        fmt.Println (Word)
        if Word == "DC" {
          break
        }
    }
    // other code
}
4
Richard Chambers

Utilisez break {label} pour sortir d'une boucle aussi imbriquée que vous le souhaitez. Il suffit de mettre l’étiquettebeforela boucle for que vous souhaitez interrompre. Ceci est assez similaire au code qui fait un goto {label} mais je pense un peu plus élégant, mais sans tenir compte de l’opinion.

package main

func main() {
    out:
    for i := 0; i < 10; i++ {
        for j := 0; j < 10; j++ {
            if i + j == 20 {
                break out
            }
        }
    }
}
2
lazieburd

Il suffit de reporter tout ce que vous devez faire et de revenir comme d'habitude.

package main

import (
    "fmt"
)

func main() {
    defer func() {
        // More logic here that needs to be executed
    }()

    Word := ""

    for _, i := range "ABCDE" {
        for _, j := range "ABCDE" {
            Word = string(i) + string(j)
            fmt.Println(Word)
            if Word == "DC" {
                return
            }
        }
    }
}
1
krob0lt