211

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?

Jonathan Hall
  • 75,165
  • 16
  • 143
  • 189
Matt
  • 21,026
  • 18
  • 63
  • 115

7 Answers7

278

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.

peterSO
  • 158,998
  • 31
  • 281
  • 276
  • 19
    What's the use case of the `break` within `select {}` since only one `case` can be selected? – Julio Guerra Jun 16 '17 at 20:42
  • 22
    Because even if a single case is selected, it might have a longer implementation which uses break to terminate the execution of the case, much like you can return from anywhere in a function. – Tit Petric Aug 25 '17 at 09:28
86

A hopefully illustrative example:

loop:
for {
        switch expr {
        case foo:
                if condA {
                        doA()
                        break // like 'goto A'
                }

                if condB {
                        doB()
                        break loop // like 'goto B'                        
                }

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

B:
doY()
// ....
zzzz
  • 87,403
  • 16
  • 175
  • 139
27

Yes, break breaks the inner 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("start")
        case x == 5:
            fmt.Println("stop")
            break myloop
        case x > 2:
            fmt.Println("crunching..")
            break
        default:
            fmt.Println("idling..")
        }
    }
}
0idling..
1start
2idling..
3crunching..
4crunching..
5stop

Program exited.
Antoine Cotten
  • 2,673
  • 18
  • 37
anatoly techtonik
  • 19,847
  • 9
  • 124
  • 140
  • 4
    this answer does not demonstrate how the `break` statement without label can be useful. the `break` statement in `case x > 2:` is effectively a no-op. – HairOfTheDog Mar 16 '21 at 01:08
22

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 <-msg:
        // do your task here
    case <-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; {

}
HaiTH
  • 925
  • 9
  • 9
  • 10
    If you don't want to leak the loop variable you can also declare it inside the scope of the for loop `for loop := true; loop; {}`. Playground: https://play.golang.org/p/dNChUECkbfd – Vaelin Dec 31 '20 at 18:59
8

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

raina77ow
  • 103,633
  • 15
  • 192
  • 229
3

this should explain it.

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

Runs forever

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

Again, runs forever

BUT

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")
    }
}
}

will print sjus ... clear ?

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

Jasmeet Singh
  • 2,347
  • 1
  • 11
  • 10
0

It only exits the switch block.

AJ Richardson
  • 6,610
  • 1
  • 49
  • 59
Sebastian
  • 45
  • 2