Как использовать 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 для чтения последней конфигурации?


person inari6    schedule 04.02.2017    source источник
comment
Ваш код работает должным образом и правильно запускает OnConfigChange в моей среде Linux. Вы должны написать свою ОС и, возможно, смонтировать опцию /tmp/, чтобы получить помощь.   -  person ymonad    schedule 05.02.2017
comment
Спасибо за ваш быстрый ответ. Я переместил свою конфигурацию в текущий рабочий каталог, и это сработало.   -  person inari6    schedule 06.02.2017


Ответы (1)


комментарий от ymonad находится на правильном пути, в зависимости от вашей ОС у вас могут возникнуть проблемы с viper/fsnotify.

Например, я запустил ваш пример кода в Mac OS X (Sierra) и заметил тот же симптом, который вы описали: когда файл конфигурации находится в /tmp, вызов viper WatchConfig не вызывал вызов функции viper OnConfigChange.

Однако, когда я изменяю AddConfigPath для использования текущего рабочего каталога или моего домашнего каталога, я вижу регистрацию из вашей функции OnConfigChange. Например, попробуйте:

v.AddConfigPath("./")

Я бы рекомендовал поэкспериментировать с разными местоположениями каталогов, чтобы увидеть, является ли это какой-то ошибкой или ограничением viper/fsnotify. По какой-то причине он не обнаруживает изменения из каталога /tmp в Mac OS X, по крайней мере, для моей установки. Я не смог найти никаких упоминаний о проблемах с /tmp в OS X, но fsnotify CONTRIBUTING.md упоминает ограничения для «общих» каталогов в Vagrant, поэтому, возможно, есть некоторые конфигурации файловой системы, которые не вызывают уведомления:

Примечание: события файловой системы fsnotify не будут запускаться в общих папках. Тесты обходят это ограничение, используя каталог /tmp.

Кроме того, вам не нужно продолжать вызывать WatchConfig и OnConfigChange через вашу горутину. Вы можете полностью исключить горутину и просто переместить соответствующие строки в init.

person Drew MacInnis    schedule 06.02.2017
comment
Спасибо за ваш быстрый ответ. На моем Mac я переместил конфигурацию в текущий рабочий каталог, и это сработало. Я также переместил WatchConfig и OnConfigChange в функцию инициализации. - person inari6; 06.02.2017