优先处理 Select 个具有频道的案例

Priority on Select cases with channel

我有这个功能让里面的方法,运行就一个ticker。我的问题是第二种情况 sigC 仅在 ticker.C 完成 后才有效 ,这并不理想,因为程序运行s 带有标志,所以如果我想更改标志并改变程序的行为,我必须等待 ticker 方法完成 运行ning,这可能需要一些时间。

我的objective是当我按Ctrl+C的时候,程序马上就结束了运行ning

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]

[2]Priority in Go select statement workaround

如果我理解正确的话,您想做的是用无限循环替换 range-over-channel 循环。即 for range ticker.C { ... } -> for { ... }.

并且如果您希望程序而不是 report 函数立即完成而不等待 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)
        }
    }
}