如何在Golang中打破嵌套循环?

Jay*_*ran 13 loops go

我有一个外部和内部循环,每个循环遍历一个范围.我想在内循环内满足条件时退出外循环.

我有一个解决方案,使用两个'break',一个在内循环内,一个在outerloop内,就在内循环之外.这是(一个非常简化的演示案例):

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
}
Run Code Online (Sandbox Code Playgroud)

这个解决方案没有问题,但它看起来只是修补和丑陋.有一个更好的方法吗?

我可以尝试在前一个解决方案中使用外部循环之外的条件循环,并使用标签并继续使用标签,就像这样.但正如您所看到的,这种方法并不比具有中断的解决方案更优雅.

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
}
Run Code Online (Sandbox Code Playgroud)

我在这里看到了与其他语言有关的类似问题(C,C#,Python等).但我真正感兴趣的是golang构造是否有任何技巧,例如'for select'.

kke*_*ley 16

使用功能

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
                }
            }
        }
    }
    return word
}

func main(){
    word := getWord()
}
Run Code Online (Sandbox Code Playgroud)

编辑:感谢@peterSO指出了细节上的一些错误并提供了这个游乐场https://play.golang.org/p/udcJptBW9pQ

  • 您没有将它用作函数,因为它可以在其他地方使用,或者是通用的.您正在使用某个功能,因为它可以解决您的问题.+1 (2认同)

laz*_*urd 12

使用break {label}打破任何环路出嵌套的,只要你想。只需将标签放在要中断的循环之前for即可。这与执行的代码相当相似,goto {label}但我认为有点优雅,但我认为是意见问题。

package main

func main() {
    out:
    for i := 0; i < 10; i++ {
        for j := 0; j < 10; j++ {
            if i + j == 20 {
                break out
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

更多详细信息:https : //www.ardanlabs.com/blog/2013/11/label-breaks-in-go.html

  • 这显然是正确的答案。“返回”解决方案或多或少是一种解决方法(如果在函数内部可能有用,但并非总是如此) (2认同)

aul*_*mus 7

怎么样?

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
}
Run Code Online (Sandbox Code Playgroud)

  • goto 是邪恶的,但在这种情况下我认为它是最简单的解决方案。 (5认同)

Ric*_*ers 6

最直接的似乎是:

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
}
Run Code Online (Sandbox Code Playgroud)

使用生成器的替代方法

但是,您也可以使用生成器来创建单词序列,如下所示:

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
}
Run Code Online (Sandbox Code Playgroud)

  • @Jayachandran是的,但更改是对中断条件进行了一次评估,因此您没有重复的检查。我的意思是,您的第一个解决方案似乎很好,尽管我会进行更改以评估出口条件,如果可能的话,然后仅检查评估的条件。这样,您可以减少将来在所有正确的地方都无法做出更改的风险。 (2认同)

小智 6

将 for 循环包装在匿名自调用函数中,然后在需要突破时返回

package main

func main() {
    func() {
        for i:= 0; i < 100; i++ {
            for j:= 0; j < 100; j++ {
                if (i == 5 && j == 5) {
                    return
                }
            }
        }
    }()
}
Run Code Online (Sandbox Code Playgroud)


小智 5

只需推迟您需要做的任何事情并正常返回。

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
            }
        }
    }
}
Run Code Online (Sandbox Code Playgroud)