英文:
Priority on Select cases with channel
问题
我有这个函数,使得其中的方法在一个定时器上运行。我的问题是,第二个 case sigC 只有在 case ticker.C 完成后才起作用,这并不理想,因为程序是带有标志的运行的,所以如果我想改变标志并改变程序的行为,我必须等待定时器方法运行完成,而这可能需要一些时间。
我的目标是,当我按下 Ctrl+C 时,程序立即停止运行。
func report() error {
ticker := time.NewTicker(timeConfig)
sigC := make(chan os.Signal, 1)
signal.Notify(sigC, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, os.Interrupt)
for range ticker.C {
select {
case <-ticker.C:
connection = connectionInit()
tagValues, err := fetchLatestTags()
if err != nil {
return err
}
if len(tagValues) >= threshold {
metrics, err := fetchMetrics(tagValues)
if err != nil {
return err
}
if stdout {
err = locally(metrics)
if err != nil {
return err
}
} else {
err = sendMail(metrics)
if err != nil {
return err
}
}
}
connection.Close()
case <-sigC:
return nil
}
}
return nil
}
我尝试了这些解决方案,它们非常相似,但都没有成功:
[1]https://stackoverflow.com/questions/46200343/force-priority-of-go-select-statement
[2]https://stackoverflow.com/questions/11117382/priority-in-go-select-statement-workaround
英文:
I have this function so that the methods inside, run on a ticker. My problem is that the second case, sigC, only works after the case ticker.C is complete, which is not ideal because the program runs with flags, so if I want to change the flags and alter the program's behaviour, I have to wait for the ticker methods to finish running, and that can take some time.
My objective is that when I press Ctrl+C, the program finishes running immediately.
func report() error {
ticker := time.NewTicker(timeConfig)
sigC := make(chan os.Signal, 1)
signal.Notify(sigC, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, os.Interrupt)
for range ticker.C {
select {
case <-ticker.C:
connection = connectionInit()
tagValues, err := fetchLatestTags()
if err != nil {
return err
}
if len(tagValues) >= threshold {
metrics, err := fetchMetrics(tagValues)
if err != nil {
return err
}
if stdout {
err = locally(metrics)
if err != nil {
return err
}
} else {
err = sendMail(metrics)
if err != nil {
return err
}
}
}
connection.Close()
case <-sigC:
return nil
}
}
return nil
}
I tried these solutions which are pretty similar to each other but to no avail:
[1]https://stackoverflow.com/questions/46200343/force-priority-of-go-select-statement
[2]https://stackoverflow.com/questions/11117382/priority-in-go-select-statement-workaround
答案1
得分: 2
如果我理解正确,你想要将循环遍历通道的部分替换为一个无限循环。即 for range ticker.C { ... }
-> for { ... }
。
如果你希望程序在不等待 case <-ticker.C:
块中的代码执行完毕时立即结束,你应该在一个单独的 goroutine 中执行该代码块,并将 case <-sigC:
块中的 return nil
更新为 os.Exit(1)
。
func report() {
ticker := time.NewTicker(timeConfig)
defer ticker.Stop()
sigC := make(chan os.Signal, 1)
signal.Notify(sigC, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, os.Interrupt)
for {
select {
case <-ticker.C:
go func() {
connection = connectionInit()
tagValues, err := fetchLatestTags()
if err != nil {
return
}
if len(tagValues) >= threshold {
metrics, err := fetchMetrics(tagValues)
if err != nil {
return
}
if stdout {
err = locally(metrics)
if err != nil {
return
}
} else {
err = sendMail(metrics)
if err != nil {
return
}
}
}
connection.Close()
}()
case <-sigC:
os.Exit(1)
}
}
}
英文:
If I understood correctly what you want to do is to replace the range-over-channel loop with an infinite loop. i.e. for range ticker.C { ... }
-> for { ... }
.
And if you want the program, rather than the report
function, to finish immediately without waiting on the code in the case <-ticker.C:
block to finish, you should execute that block of code in a separate goroutine and update the case <-sigC:
block from return nil
to os.Exit(1)
.
func report() {
ticker := time.NewTicker(timeConfig)
defer ticker.Stop()
sigC := make(chan os.Signal, 1)
signal.Notify(sigC, syscall.SIGHUP, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT, os.Interrupt)
for {
select {
case <-ticker.C:
go func() {
connection = connectionInit()
tagValues, err := fetchLatestTags()
if err != nil {
return
}
if len(tagValues) >= threshold {
metrics, err := fetchMetrics(tagValues)
if err != nil {
return
}
if stdout {
err = locally(metrics)
if err != nil {
return
}
} else {
err = sendMail(metrics)
if err != nil {
return
}
}
}
connection.Close()
}()
case <-sigC:
os.Exit(1)
}
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论