-2

I'm learning Go on my own time. Going through tutorials. Looking at the code below and can't figure out how does it stop its executing. Would someone care to help?

package main

import (
    "fmt"
)

func main() {
    ch1 := make(chan int, 2)
    ch1 <- 1
    ch1 <- 2
    ch2 := make(chan int, 2)
    ch2 <- 3
LOOP:
    for {
        select {
        case v1 := <-ch1:
            fmt.Println("chan1 val", v1)
        case v2 := <-ch2:
            fmt.Println("chan2 val", v2)
        default:
            break LOOP
        }
    }
}
flashburn
  • 4,180
  • 7
  • 54
  • 109
  • 4
    A Go program exits when `main()` returns. – Adrian May 19 '20 at 19:07
  • @Adrian I know that. But I feel like I'm missing something. My expectation is that when `break LOOP` is executed the program jump back to the beginning of the for loop. Am I missing something? – flashburn May 19 '20 at 19:09
  • 2
    It seems you're missing what `break` does. It breaks out of the loop. `continue` continues the loop. But since there's nothing after the `select`, you could also have an empty `default` and it would also continue the loop. – Adrian May 19 '20 at 19:18

2 Answers2

1

From the select documentation.

If one or more of the communications can proceed, a single one that can proceed is chosen via a uniform pseudo-random selection. Otherwise, if there is a default case, that case is chosen. If there is no default case, the "select" statement blocks until at least one of the communications can proceed.

Once neither channel is ready to read, in this case because they've been exhausted, default will run. break LOOP jumps out of the labelled for loop the select is inside, main exits, and the program terminates.

Schwern
  • 153,029
  • 25
  • 195
  • 336
  • Feels like I'm missing something. When `break LOOP` executes, I expect it to go to the `LOOP` label which restarts the the for loop. Am I wrong? – flashburn May 19 '20 at 19:07
  • 2
    @flashburn `LOOP` is not before the `for` loop, it is labeling the `for` loop. Ignore the newline, it's `LOOP: for`. `break LABEL` is just like a regular `break`, but it makes it explicit which loop to break. Normally it's used to break out of an outer loop from inside an inner one. `OUTER: for { for { for { break OUTER } } }; fmt.Println("Break jumps here")` – Schwern May 19 '20 at 19:10
  • I see. That's what tripped me up. To clarify, it makes sense to use the label if there are multiple loops, doesn't really makes sense to use it when there is only one loop. Am I correct here? Or one can use `break` in `select` statement as well and that's why we need a `LOOP` label. In other words we didn't really need to use a `LOOP` label in the code, we could have gotten away with plain `break` – flashburn May 19 '20 at 19:18
  • 1
    @flashburn The label is necessary because [`break` also terminates `select`](https://stackoverflow.com/questions/11104085/in-go-does-a-break-statement-break-from-a-switch-select). I encourage you to try modifying the program and running it to see what happens. – Schwern May 19 '20 at 19:32
  • Thanks! Really appreciate your comments. – flashburn May 19 '20 at 19:37
0

The default case of a select is selected when none of the other cases are ready. After you read everything from both channels, none of them are ready, so default case is selected, which breaks from the loop.

Burak Serdar
  • 46,455
  • 3
  • 40
  • 59