英文:
How to use golang viper Watchconfig & onConfigChange
问题
我正在尝试使用golang的viper库读取我的应用程序配置,并希望始终读取最新的配置。请查看下面的代码:
config.go
package config
import (
"github.com/spf13/viper"
"log"
"github.com/fsnotify/fsnotify"
"time"
)
type Reader interface {
GetAllKeys() []string
Get(key string) interface{}
GetBool(key string) bool
GetString(key string) string
}
type viperConfigReader struct {
viper *viper.Viper
}
var TestConfReader *viperConfigReader
func (v viperConfigReader) GetAllKeys() []string{
return v.viper.AllKeys()
}
func (v viperConfigReader) Get(key string) interface{} {
return v.viper.Get(key)
}
func (v viperConfigReader) GetBool(key string) bool {
return v.viper.GetBool(key)
}
func (v viperConfigReader) GetString(key string) string {
return v.viper.GetString(key)
}
func init() {
v:= viper.New()
v.SetConfigName("test")
v.AddConfigPath("/tmp/")
err := v.ReadInConfig()
if err != nil {
log.Panic("Not able to read configuration", err.Error())
}
TestConfReader = &viperConfigReader{
viper: v,
}
go func() {
for {
time.Sleep(time.Second * 5)
v.WatchConfig()
v.OnConfigChange(func(e fsnotify.Event) {
log.Println("config file changed", e.Name)
})
}
}()
}
main.go
package main
import (
"github.com/xxxx/xxxx/config"
"log"
"time"
)
func main() {
conf := config.TestConfReader
log.Println(conf.GetAllKeys())
log.Println(conf.GetString("test1"))
time.Sleep(20 * time.Second)
log.Println(conf.GetString("test1"))
}
当主程序运行时,我尝试更新配置,并期望看到"OnConfigChange"的日志消息,但从未显示出来。
你可以如何修复这个程序?
有人可以提供一个使用viper的WatchConfig和OnConfigChange方法读取最新配置的示例吗?
英文:
I am trying to read my application configuration using golang viper and would like to read the latest config always. Please find my code below
config.go
package config
import (
"github.com/spf13/viper"
"log"
"github.com/fsnotify/fsnotify"
"time"
)
type Reader interface {
GetAllKeys() []string
Get(key string) interface{}
GetBool(key string) bool
GetString(key string) string
}
type viperConfigReader struct {
viper *viper.Viper
}
var TestConfReader *viperConfigReader
func (v viperConfigReader) GetAllKeys() []string{
return v.viper.AllKeys()
}
func (v viperConfigReader) Get(key string) interface{} {
return v.viper.Get(key)
}
func (v viperConfigReader) GetBool(key string) bool {
return v.viper.GetBool(key)
}
func (v viperConfigReader) GetString(key string) string {
return v.viper.GetString(key)
}
func init() {
v:= viper.New()
v.SetConfigName("test")
v.AddConfigPath("/tmp/")
err := v.ReadInConfig()
if err != nil {
log.Panic("Not able to read configuration", err.Error())
}
TestConfReader = &viperConfigReader{
viper: v,
}
go func() {
for {
time.Sleep(time.Second * 5)
v.WatchConfig()
v.OnConfigChange(func(e fsnotify.Event) {
log.Println("config file changed", e.Name)
})
}
}()
}
main.go
package main
import (
"github.com/xxxx/xxxx/config"
"log"
"time"
)
func main() {
conf := config.TestConfReader
log.Println(conf.GetAllKeys())
log.Println(conf.GetString("test1"))
time.Sleep(20 * time.Second)
log.Println(conf.GetString("test1"))
}
When the main program is running, I tried to update the config and expected to see OnConfigChange log message but it never showed up.
How can I fix this program ?.
Can someone provide an example of using viper watchconfig & onconfigchange methods to read the latest config
答案1
得分: 3
ymonad的评论是正确的,根据你的操作系统,你可能会遇到viper/fsnotify的问题。
例如,我在Mac OS X(Sierra)上运行了你的示例代码,并注意到你描述的相同症状:当配置文件位于/tmp
时,viper的WatchConfig
调用不会触发viper的OnConfigChange
函数。
然而,当我将AddConfigPath
更改为使用当前工作目录或我的主目录时,我确实能够看到来自你的OnConfigChange
函数的日志。例如,尝试一下:
v.AddConfigPath("./")
我建议尝试不同的目录位置,看看这是否是viper/fsnotify的某种错误或限制。由于某种原因,在Mac OS X上,它似乎无法检测到/tmp
目录中的更改,至少对于我的设置来说是这样。我在OS X上找不到关于/tmp
的任何问题的提及,但是fsnotify的CONTRIBUTING.md提到了在Vagrant下的“共享”目录的限制,因此可能存在一些文件系统配置不会触发通知的情况:
> 注意:在共享文件夹中,fsnotify文件系统事件不会触发。测试通过使用/tmp目录来解决这个限制。
另外,你不需要通过goroutine不断调用WatchConfig
和OnConfigChange
。你可以完全消除goroutine,并将相关行移到init
函数中。
英文:
The comment by ymonad is on the right track, depending on your OS you may be experiencing problems with viper/fsnotify.
For example, I ran your example code on Mac OS X (Sierra) and noticed the same symptom you described: when the config file is in /tmp
the viper WatchConfig
call was not causing the viper OnConfigChange
function to be called.
However, when I change the AddConfigPath
to use the current working directory or my home directory then I do see logging from your OnConfigChange
function. For example, try:
v.AddConfigPath("./")
I'd recommend experimenting with different directory locations to see if this is some sort of viper/fsnotify bug or limitation. For some reason, it doesn't appear to detect changes from the /tmp
directory on Mac OS X, at least, it doesn't for my setup. I couldn't find any mention of problems with /tmp
on OS X, but the fsnotify CONTRIBUTING.md does mention limitations with "shared" directories under Vagrant so perhaps there are some filesystem configurations that do not trigger notifications:
> Notice: fsnotify file system events won't trigger in shared folders. The tests get around this limitation by using the /tmp directory.
Also, you don't need to keep calling WatchConfig
and OnConfigChange
via your goroutine. You can eliminate the goroutine completely and just move the relevant lines into init
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论