英文:
Stop time.NewTimer initialized inside for loop
问题
我有一个类似下面程序的程序:
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan string)
go endProgram(ch)
printFunc(ch)
}
func printFunc(ch chan string) {
for {
timeout := time.NewTimer(getTimeoutDuration())
defer timeout.Stop()
select {
case s := <-ch:
fmt.Println(s)
return
case <-timeout.C:
fmt.Println("Current value")
}
}
}
func endProgram(ch chan string) {
time.Sleep(time.Second * 8)
ch <- "Exit function"
}
func getTimeoutDuration() time.Duration {
return time.Second * 3
}
在这种情况下,停止timeout
计时器的最佳方法是什么?
我知道上面的方法不是推荐的方式,因为在循环中使用defer
是一种不好的做法。替代方法是在循环中使用time.After
而不是time.NewTimer
,因为我们不需要停止time.After
。但是,如果函数在计时器触发之前退出,time.After
会导致资源泄漏(来源)。
英文:
I have a program similar to below program:
package main
import (
"fmt"
"time"
)
func main() {
ch := make(chan string)
go endProgram(ch)
printFunc(ch)
}
func printFunc(ch chan string) {
for {
timeout := time.NewTimer(getTimeoutDuration())
defer timeout.Stop()
select {
case s := <-ch:
fmt.Println(s)
return
case <-timeout.C:
fmt.Println("Current value")
}
}
}
func endProgram(ch chan string) {
time.Sleep(time.Second * 8)
ch <- "Exit function"
}
func getTimeoutDuration() time.Duration {
return time.Second * 3
}
What is the best way to stop the timeout
timer in this case?
I know that above is not the recommended way because it is a bad practice to use defer inside for loop. Alternative is to use time.After
inside the for loop instead of time.NewTimer
as we don't have to stop time.After
. But time.After
causes resource leak if function exits before the timer fires(Source).
答案1
得分: 1
如果您使用上下文而不是计时器,那么只有在退出函数的情况下才会调用取消函数。
package main
import (
"context"
"fmt"
"time"
)
func main() {
ch := make(chan string)
go endProgram(ch)
printFunc(ch)
}
func printFunc(ch chan string) {
for {
ctx, cancel := context.WithTimeout(context.Background(), getTimeoutDuration())
select {
case s := <-ch:
cancel()
fmt.Println(s)
return
case <-ctx.Done():
fmt.Println("当前值")
}
}
}
func endProgram(ch chan string) {
time.Sleep(time.Second * 8)
ch <- "退出函数"
}
func getTimeoutDuration() time.Duration {
return time.Second * 3
}
英文:
if you use context instead of timer, Where cancel only called when exiting function case condition.
package main
import (
"context"
"fmt"
"time"
)
func main() {
ch := make(chan string)
go endProgram(ch)
printFunc(ch)
}
func printFunc(ch chan string) {
for {
ctx, cancel := context.WithTimeout(context.Background(), getTimeoutDuration())
select {
case s := <-ch:
cancel()
fmt.Println(s)
return
case <-ctx.Done():
fmt.Println("Current value")
}
}
}
func endProgram(ch chan string) {
time.Sleep(time.Second * 8)
ch <- "Exit function"
}
func getTimeoutDuration() time.Duration {
return time.Second * 3
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论