GO的Viper的问题,哪位大佬能帮我解答一下呀?

目前使用的是直接读取app.ini配置文件,然后再映射,简单粗暴,但是问题就是不能实时动态修改,所以上网寻找解决方案,看到大家都推荐Viper,所以尝试了一下,但是发现了个问题,虽然能够动态获取到改变的值,但是这个值并没有在程序中生效哇,具体问题解释如下:

app.ini

[kafka]
TimeExec = 20

main.go:

func main() {
    viper.SetConfigName("app")
    viper.SetConfigType("ini")
    viper.AddConfigPath(".")
    err := viper.ReadInConfig()
    if err != nil {
        log.Fatal("read config failed: %v", err)
    }

    viper.WatchConfig()

    viper.OnConfigChange(func(e fsnotify.Event) {
        fmt.Println("Config file changed:", e.Name)
    })


    // 执行定时任务
    ticker := time.NewTicker(viper.GetDuration("kafka.TimeExec"))
    defer ticker.Stop()

    for {
        select {
        case <-ticker.C:
            fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
            fmt.Println("间隔:" + viper.GetDuration("kafka.TimeExec"))
        }
    }
}

启动程序,项目20s执行一次,并且打印出间隔 20s。

这时候当我更改了配置文件,改为10s,确实会监控到并且也会执行OnConfigChange打印信息、也会打印出:间隔:10s,但是定时还是20s执行一次呀,这是为什么呢?

阅读 2.4k
2 个回答

time.NewTicker 方法执行的时候创建了 ticker ,创建的时候指定了间隔时间,那么这个 ticker 就会以这个间隔时间执行。

最简单的修改思路是,当文件变更时,调用 Reset 方法重置 ticker 的间隔时间。

func main() {
    viper.SetConfigName("app")
    viper.SetConfigType("ini")
    viper.AddConfigPath(".")
    err := viper.ReadInConfig()
    if err != nil {
        log.Fatal("read config failed: %v", err)
    }

    viper.WatchConfig()

    // 执行定时任务
    ticker := time.NewTicker(viper.GetDuration("kafka.TimeExec") * time.Second)
    defer ticker.Stop()

    viper.OnConfigChange(func(e fsnotify.Event) {
        fmt.Println("Config file changed:", e.Name)
        ticker.Reset(viper.GetDuration("kafka.TimeExec") * time.Second)
    })

    for {
        select {
        case <-ticker.C:
            fmt.Println(time.Now().Format("2006-01-02 15:04:05"))
            fmt.Println("间隔:", viper.GetDuration("kafka.TimeExec")*time.Second)
        }
    }
}

image.png

我有个疑问?为什么要写执行定时任务那一堆的代码,viper.OnConfigChange 完全可以处理
重新再读取下,放到全局变量就可以


viper.OnConfigChange(func(in fsnotify.Event) {
        ReadConfig(viper)
})
func ReadConfig(v *viper.Viper) {
    v.ReadInConfig()
    err := v.Unmarshal(global.xxxConfig)
    if err != nil {
        panic(err)
    }
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题