英文:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论