是 time.Tick 导致内存泄漏,因为你无法显式关闭通道,因为它是 Go 中的仅接收通道? return语句解决了吗

问题描述 投票:0回答:1

假设我有一个如下函数:

func fetchData() {
    interval := time.Minutes * 15
    ticker := time.Tick(interval)
    for {
        select {
        case <-ticker:
            fetchSomething()
        case <-stopFetching:
            return
        }
    }
}

假设该函数的调用方式如下:

go fetchData()

想象一下,

stopFetching
只是一个通道,当它被触发时,
return
语句将执行。

这样的话,这里会不会出现关于

ticker
的内存泄漏呢?因为它不能用
close(ticker)
关闭,因为它是仅接收通道。如何优雅地处理这件事。当我编写代码时,静态检查器警告我说
using time.Tick leaks the underlying ticker, consider using it only in endless functions, tests and the main package, and use time.NewTicker here (SA1015)

我不知道在这里做什么..

go memory timer channel goroutine
1个回答
0
投票

引用

time.Tick()

Tick 是 NewTicker 的便捷包装器,仅提供对滴答通道的访问。 虽然 Tick 对于不需要关闭 Ticker 的客户端很有用,但请注意,如果没有办法关闭它,底层 Ticker 就无法被垃圾收集器恢复;它“泄漏”。 与 NewTicker 不同,如果 d <= 0.

,Tick 将返回 nil

医生说,当您不想(不必)关闭

Ticker
时,它很有用。既然您确实想关闭它,请不要使用
time.Tick()

而是使用

time.NewTicker()
,您可以调用其中的
Ticker.Stop()
方法来释放关联资源。

例如:

func fetchData() {
    interval := time.Minute * 15
    ticker := time.NewTicker(interval)
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            fetchSomething()
        case <-stopFetching:
            return
        }
    }
}

以下是测试方法(将

interval
更改为 1 秒):

func main() {
    time.AfterFunc(time.Second*10, func() {
        close(stopFetching)
    })
    fetchData()
}

func fetchSomething() {
    fmt.Println("Fetching something")
}

这将输出

Fetching something
10 次然后停止。在Go Playground尝试一下。

© www.soinside.com 2019 - 2024. All rights reserved.