首页 >后端开发 >Golang >在 Golang 中使用 Ticker Channel 时如何正确终止 Goroutine?

在 Golang 中使用 Ticker Channel 时如何正确终止 Goroutine?

Patricia Arquette
Patricia Arquette原创
2024-11-07 19:16:02491浏览

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

Golang 中的股票行情通道行为

如果您迭代股票行情通道并调用 Stop(),通道将暂停但不会关闭。这可能会导致 goroutine 无限期地保持活动状态。

案例示例:

考虑以下代码片段:

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)
}

输出:

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

当你可以看到,尽管停止了 Ticker,goroutine 仍会继续无限期地迭代,因为通道未关闭。

解决方案:

确保 goroutine 终止的一种方法是使用第二个通道,如下所示:

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)
}

在此代码:

  • Every 函数创建两个通道:一个股票行情通道和一个停止通道。
  • goroutine 迭代两个通道。
  • 如果工作函数返回false,通知stop通道,导致goroutine退出。
  • 当调用Stop()时,它会向stop发送消息通道,它终止 goroutine。

以上是在 Golang 中使用 Ticker Channel 时如何正确终止 Goroutine?的详细内容。更多信息请关注PHP中文网其他相关文章!

声明:
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn