A simple golang example with concurrency – doesn't work as expected

Issue

I am learning golang and have built a simple timer to understand how channels work:

package main

import (
    "fmt"
    "time"
)

func tick(tc chan time.Time, done chan bool) {
    ticker := time.Tick(500 * time.Millisecond)

    for {
        select {
        case <-done:
            return
        case tc <- <-ticker:
            continue
        }
    }
}

func stop(done chan bool) {
    time.Sleep(1600 * time.Millisecond)
    done <- true
}

func main() {

    tc := make(chan time.Time)
    done := make(chan bool)

    go tick(tc, done)
    go stop(done)

    for i := range tc {
        fmt.Println(i)
    }

    fmt.Println("Ticker stopped")
    panic("now")
}

It doesn’t quite work as expected. When you start it in go playground, it outputs a few timer lines (as expected) but it does not output Ticker stopped or the stack trace resulted from calling panic, and I don’t understand why. Any ideas?

Solution

for ... range on a channel breaks when the channel is closed.

The program is blocks on for i := range tc { } because tc is never closed.

Fix by adding this line to the beginning of tick:

 defer close(tc)

Answered By – Zombo

Answer Checked By – Candace Johnson (GoLangFix Volunteer)

Leave a Reply

Your email address will not be published.