Home >Backend Development >Golang >How to Properly Terminate a Goroutine When Using a Ticker Channel in Golang?

How to Properly Terminate a Goroutine When Using a Ticker Channel in Golang?

Patricia Arquette
Patricia ArquetteOriginal
2024-11-07 19:16:02521browse

How to Properly Terminate a Goroutine When Using a Ticker Channel in Golang?

Ticker Channel Behavior in Golang

If you iterate over a ticker channel and call Stop(), the channel will pause but not close. This can lead to goroutines remaining active indefinitely.

Case Example:

Consider the following code snippet:

package main

import (
    "fmt"
    "time"
)

func main() {
    ticker := time.NewTicker(1 * time.Second)
    go func() {
        for _ = range ticker.C {
            fmt.Println("tick")
        }
    }()
    time.Sleep(3 * time.Second)
    fmt.Println("stopping ticker")
    ticker.Stop()
    time.Sleep(3 * time.Second)
}

Output:

2013/07/22 14:26:53 tick
2013/07/22 14:26:54 tick
2013/07/22 14:26:55 tick
2013/07/22 14:26:55 stopping ticker

As you can see, despite stopping the ticker, the goroutine continues to iterate indefinitely because the channel is not closed.

Solution:

One way to ensure the goroutine terminates is to use a second channel as follows:

package main

import (
    "fmt"
    "log"
    "time"
)

// Run the function every tick
// Return false from the func to stop the ticker
func Every(duration time.Duration, work func(time.Time) bool) chan bool {
    ticker := time.NewTicker(duration)
    stop := make(chan bool, 1)

    go func() {
        defer log.Println("ticker stopped")
        for {
            select {
            case time := <-ticker.C:
                if !work(time) {
                    stop <- true
                }
            case <-stop:
                return
            }
        }
    }()

    return stop
}

func main() {
    stop := Every(1*time.Second, func(time.Time) bool {
        fmt.Println("tick")
        return true
    })

    time.Sleep(3 * time.Second)
    fmt.Println("stopping ticker")
    stop <- true
    time.Sleep(3 * time.Second)
}

In this code:

  • The Every function creates two channels: a ticker channel and a stop channel.
  • The goroutine iterates over both channels.
  • If the work function returns false, the stop channel is notified, causing the goroutine to exit.
  • When Stop() is called, it sends a message to the stop channel, which terminates the goroutine.

The above is the detailed content of How to Properly Terminate a Goroutine When Using a Ticker Channel in Golang?. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn