为什么分配了 time.Afterfunc 的 Timer 变量即使外部 func 退出也会执行其函数

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

我有一个永远循环,它有一个 Timer 变量,在一段时间后执行一个函数。

package main

import (
    fmt "fmt"
    "time"
)

func exe() {
    fmt.Println("10-seconds-of-time-is-done")
}

func t() {
    var timerCheck *time.Timer
    fmt.Println("here's the timerCheck", timerCheck)
    for {
        timerCheck = time.AfterFunc(10*time.Second, func() { exe() })
        fmt.Println("exiting-from-function-t")
        return
    }
}

func main() {
    t()
    fmt.Println("waiting-inside-main")
    time.Sleep(20 * time.Second)
}

这是输出。我不明白函数

t()
立即返回,但
timerCheck
在 10 秒后执行其
exe()
函数。

here's the timerCheck <nil>
exiting-from-function-t
waiting-inside-main
10-seconds-of-time-is-done

这怎么可能?在标准库中,关于

AfterFunc

的说法如下
// AfterFunc waits for the duration to elapse and then calls f
// in its own goroutine. It returns a Timer that can
// be used to cancel the call using its Stop method.
func AfterFunc(d Duration, f func()) *Timer {
    t := &Timer{
        r: runtimeTimer{
            when: when(d),
            f:    goFunc,
            arg:  f,
        },
    }
    startTimer(&t.r)
    return t
}

我希望所有与timerCheck`相关的东西都应该被释放,因为外部函数的工作已经完成,基本上这个函数的堆栈被释放了(我猜:/)。

为了检查堆栈/堆分配,输出如下;

./main.go:9:13: ... argument does not escape
./main.go:9:14: "10-seconds-of-time-is-done" escapes to heap
./main.go:14:13: ... argument does not escape
./main.go:14:14: "here's the timerCheck" escapes to heap
./main.go:16:47: func literal escapes to heap
./main.go:17:14: ... argument does not escape
./main.go:17:15: "exiting-from-function-t" escapes to heap
./main.go:24:13: ... argument does not escape
./main.go:24:14: "waiting-inside-main" escapes to heap

func literal escapes to heap
是不是因为这个,所以
exe
功能还在运行?

我需要一些关于

timerCheck
exe()
功能如何在 10 秒后仍然有效的内部指导?即使函数
t()
立即返回。没想到会打印出这个日志
10-seconds-of-time-is-done
。因为功能
t()
已经完成了。

示例代码是可执行的,可以尝试。

go concurrency timer goroutine
1个回答
0
投票

即使函数声明它返回,定时器变量仍然存在,因为定时器创建了一个引用它的 goroutine。 goroutine 等待给定的持续时间,发送信号或调用 AfterFunc,然后终止。只有在此之后,计时器变量才能被垃圾收集。 AfterFunc 异步执行。

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