Home > Software design >  "unreachable code" after select statement in a Go program
"unreachable code" after select statement in a Go program

Time:05-30

I am playing with channels and don't quite understand why the code I wrote becomes unreachable at this point and also a deadlock arises. Shouldn't the select take the value from the quit channel and then exit from the infinite for loop?

func run(jobs []Job, receive, quit chan int) {
    for _, job := range jobs {
        go func(job Job) {
            receive <- longCalculation(job)
        }(job)
    }
    quit <- -1 // write to the channel to signal end of work
}

func main() {
    rand.Seed(time.Now().UnixNano())
    jobs := makeJobs()
    receive := make(chan int)
    quit := make(chan int)

    run(jobs, receive, quit)

    var sum int
    for {
        select {
        case data := <-receive:
            sum  = data
        case <-quit: // take the last value indicating end of work
            fmt.Println("Exiting for loop ...", quit)
            return
        }
    }
    fmt.Print(sum) -> this line says unreachable code
}

CodePudding user response:

for {
        select {
        case data := <-receive:
            sum  = data
        case <-quit: // take the last value indicating end of work
            fmt.Println("Exiting for loop ...", quit)
            return
        }
    }

Change it into

running := true
for running {
        select {
        case data := <-receive:
            sum  = data
        case <-quit: // take the last value indicating end of work
            fmt.Println("Exiting for loop ...", quit)
            running = false
            break
        }
    }

It's because the function stop immediately when you return

CodePudding user response:

You can just use a single channel & close it to signal you are done:

func run(jobs []Job, receive chan int) {

    var wg sync.WaitGroup
    wg.Add(len(jobs))

    for _, job := range jobs {
        go func(job Job) {
            defer wg.Done()

            receive <- longCalculation(job)
        }(job)
    }
    wg.Wait()
    close(receive)
}

This simplifies your read-side logic:

func main() {

    // ....

    go run(jobs, receive)

    var sum int

    for data := range receive {
        sum  = data
    }

    fmt.Print(sum)
}
  • Related