Search code examples
gogoroutine

How to stop goRoutine which repeatedly runs based on ticker


func main() {
    // Start a long-running process, capture stdout and stderr
    findCmd := cmd.NewCmd("find", "/", "--name", "needle")
    statusChan := findCmd.Start() // non-blocking

    ticker := time.NewTicker(2 * time.Second)

    // Print last line of stdout every 2s
    go func() {               ------------ this keeps running in background, how do I stop this goroutine
        for range ticker.C {
            status := findCmd.Status()
            n := len(status.Stdout)
            if len > 10 {
               findCmd.Stop()     ------- at this point I want to stop this goroutine
            }
            fmt.Println(status.Stdout[n-1])
        }
    }()

    // Stop command after 1 hour
    go func() {
        <-time.After(1 * time.Hour)
        findCmd.Stop()
    }()

    // Check if command is done
    select {
    case finalStatus := <-statusChan:
        // done
    default:
        // no, still running
    }

    // Block waiting for command to exit, be stopped, or be killed
    finalStatus := <-statusChan
}

Goroutine is used to print last line of stdout every 2s, tried few things to stop the goroutine but none worked. How can I stop that goroutine using channels


Solution

  • This is where select, case is used. You can do something like this:

    ticker := time.NewTicker(2 * time.Second)
    
    done := make(chan struct{})
    // The go routine that you want to stop when needed
    go func() {
        select {
        case <-ticker.C:
            // do stuff
        case <-done:
            ticker.Stop() // this is optional based on your purpose
        }
    }()
    
    // do stuff
    
    // stop above go routine
    close(done) // when there are many go routine you want to stop as reading from closed channel return the channel zero value
    // OR
    done <- struct{}{}  // when there is only 1 go routine you want to stop