一个break语句会从switch/select语句中跳出吗?

huangapple go评论85阅读模式
英文:

Does a break statement break from a switch/select?

问题

我知道switch/select语句在每个case之后会自动中断。我想知道,在下面的代码中:

for {
    switch sometest() {
    case 0:
        dosomething()
    case 1:
        break
    default:
        dosomethingelse()
    }
}

break语句是退出for循环还是只是退出switch块?

英文:

I know that switch/select statements break automatically after every case. I am wondering, in the following code:

for {
    switch sometest() {
    case 0:
        dosomething()
    case 1:
        break
    default:
        dosomethingelse()
    }
}

Does the break statement exit the for loop or just the switch block?

答案1

得分: 277

> Break语句,Go编程语言规范。
>
> 一个"break"语句终止最内层的"for"、"switch"或"select"语句的执行。
>
> BreakStmt = "break" [ Label ] .
>
> 如果有一个标签,它必须是一个封闭的"for"、"switch"或"select"语句的标签,而且它是终止执行的那个语句
> (§For语句,§Switch语句,§Select语句)。
>
> L:
> for i < n {
> switch i {
> case 5:
> break L
> }
> }

因此,在你的例子中,break语句终止了switch语句,即最内层的语句。
1: http://golang.org/ref/spec#Break_statements

英文:

> Break statements, The Go Programming Language Specification.
>
> A "break" statement terminates execution of the innermost "for",
> "switch" or "select" statement.
>
> BreakStmt = "break" [ Label ] .
>
> If there is a label, it must be that of an enclosing "for", "switch"
> or "select" statement, and that is the one whose execution terminates
> (§For statements, §Switch statements, §Select statements).
>
> L:
> for i < n {
> switch i {
> case 5:
> break L
> }
> }

Therefore, the break statement in your example terminates the switch statement, the "innermost" statement.
1: http://golang.org/ref/spec#Break_statements

答案2

得分: 85

一个希望能够说明问题的例子:

循环:
for {
        switch expr {
        case foo:
                if condA {
                        doA()
                        break // 类似于 'goto A'
                }

                if condB {
                        doB()
                        break loop // 类似于 'goto B'                        
                }

                doC()
        case bar:
                // ...
        }
A:
        doX()
        // ...
}

B:
doY()
// ....
英文:

A hopefully illustrative example:

loop:
for {
        switch expr {
        case foo:
                if condA {
                        doA()
                        break // like &#39;goto A&#39;
                }

                if condB {
                        doB()
                        break loop // like &#39;goto B&#39;                        
                }

                doC()
        case bar:
                // ...
        }
A:
        doX()
        // ...
}

B:
doY()
// ....

答案3

得分: 27

是的,break会中断内部的switch语句。

https://play.golang.org/p/SZdDuVjic4

package main

import "fmt"

func main() {
    myloop:
    for x := 0; x < 7; x++ {
        fmt.Printf("%d", x)
        switch {
        case x == 1:
            fmt.Println("开始")
        case x == 5:
            fmt.Println("停止")
            break myloop
        case x > 2:
            fmt.Println("处理中...")
            break
        default:
            fmt.Println("空闲中...")
        }
    }
}

输出结果:

0空闲中...
1开始
2空闲中...
3处理中...
4处理中...
5停止

程序已退出。
英文:

Yes, break breaks the inner switch.

https://play.golang.org/p/SZdDuVjic4

<!-- language: go -->

package main

import &quot;fmt&quot;

func main() {

myloop:
	for x := 0; x &lt; 7; x++ {
		fmt.Printf(&quot;%d&quot;, x)
		switch {
		case x == 1:
			fmt.Println(&quot;start&quot;)
		case x == 5:
			fmt.Println(&quot;stop&quot;)
			break myloop
		case x &gt; 2:
			fmt.Println(&quot;crunching..&quot;)
			break
		default:
			fmt.Println(&quot;idling..&quot;)
		}
	}
}

> 0idling..
> 1start
> 2idling..
> 3crunching..
> 4crunching..
> 5stop
>
> Program exited.

答案4

得分: 22

这个问题可能已经太旧了,但我仍然认为标签使我们的代码变得更难阅读。
不要在select内部中断循环,只需在调用break之前在select-case中设置一个循环标志并处理它。
例如:

loop := true
for loop {
    select {
    case <-msg:
        // 在这里执行任务
    case <-ctx.Done():
        loop = false
        break
    }
}

**更新:**完全同意评论中的Vaelin的观点。在for循环的作用域内声明该标志可以避免内存泄漏,并且可以避免与当前作用域中的其他变量冲突,以防我们已经有一个同名变量。

for loop := true; loop; {

}
英文:

This question might be too old already but I still think label makes our code become harder to read.
Instead of breaking the for inside select, just set a flag for the loop and handle it inside select-case before invoking break.
For example:

loop := true
for loop {
    select {
    case &lt;-msg:
        // do your task here
    case &lt;-ctx.Done():
        loop = false
        break
    }
}

Updated: Totally agree with Vaelin in the comment. Declaring that flag inside the scope of the for loop can avoid memory leak and conflict with other variables in current scope, just in case we have a same variable name already.

for loop := true; loop; {

}

答案5

得分: 8

只从一个switch块中退出。在Golang自己的代码中有很多例子可以检查(比较内部break外部break)。

英文:

Just from a switch block. There's plenty of examples in Golang own code you can examine (compare inner break with outer break).

答案6

得分: 3

这应该能解释清楚。

for{
    x := 1
	switch {
    case x >0:
        fmt.Println("sjus")
    case x == 1:
        fmt.Println("GFVjk")
    default:
        fmt.Println("daslkjh")
    }
}
}

无限循环

for{
    x := 1
	switch {
    case x >0:
        fmt.Println("sjus")
        break
    case x == 1:
        fmt.Println("GFVjk")
    default:
        fmt.Println("daslkjh")
    }
}
}

同样,无限循环

但是

package main

import "fmt"

func main() {
d:
for{
x := 1
	switch {
    case x >0:
        fmt.Println("sjus")
        break d
    case x == 1:
        fmt.Println("GFVjk")
    default:
        fmt.Println("daslkjh")
    }
}
}

将打印sjus
...清楚吗?

http://play.golang.org/p/GOvnfI67ih

英文:

this should explain it.

for{
    x := 1
	switch {
    case x &gt;0:
        fmt.Println(&quot;sjus&quot;)
    case x == 1:
        fmt.Println(&quot;GFVjk&quot;)
    default:
        fmt.Println(&quot;daslkjh&quot;)
    }
}
}

Runs forever

for{
    x := 1
	switch {
    case x &gt;0:
        fmt.Println(&quot;sjus&quot;)
        break
    case x == 1:
        fmt.Println(&quot;GFVjk&quot;)
    default:
        fmt.Println(&quot;daslkjh&quot;)
    }
}
}

Again, runs forever

BUT

package main

import &quot;fmt&quot;

func main() {
d:
for{
x := 1
	switch {
    case x &gt;0:
        fmt.Println(&quot;sjus&quot;)
        break d
    case x == 1:
        fmt.Println(&quot;GFVjk&quot;)
    default:
        fmt.Println(&quot;daslkjh&quot;)
    }
}
}

will print sjus
... clear ?

http://play.golang.org/p/GOvnfI67ih

答案7

得分: 0

只有退出开关块。

英文:

It only exits the switch block.

huangapple
  • 本文由 发表于 2012年6月19日 23:16:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/11104085.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定