-
Notifications
You must be signed in to change notification settings - Fork 0
Example RU
ConfigManager - это стандартное средство связи между вами и модулем mkconf. Он поможет вам создать, прочитать, обновить и начать отслеживать ваш конфиг. Если вам не нравится его реализация, вы можете создать свою собственную. В примере будет использоваться ConfigManager.
Для добавления конфигурации используется функция AddConfig, которая принимает имя конфигурации, путь к файлу конфигурации, расширение файла и указатель на структуру конфигурации.
cm := mkconf.NewConfigManager()
configPath := "C:\\My saved files\\testConfig" configName := "config"
cm.AddConfig(configName, configPath, ".json", &cf1)&cf1 - это указатель на вашу структуру конфигурации:
type MyConfig struct {
Key string `json:"key"`
Value int `json:"value"`
}Эти методы запускают отслеживание изменений и начинают мониторинг изменений для конфигурации с именем config. Вы можете получать только уведомление об изменениях, только историю изменений или и то, и другое.
cm.StartAllLogChanges()
cm.StartChangeMonitoring("config", cf1)Чтобы использовать их, необходимо определить функции обратного вызова:
changeCallback := func(configName string) {
myCallbacks1(cm, configName, &cf1)
}
trackingCallback := func(configName string) {
myCallbacks2(cm, configName)
}
cm.ChangeCallbackFunc(configName, changeCallback)
cm.TrackingCallbackFunc(configName, trackingCallback)Мои функции обратного вызова выглядят следующим образом:
func myCallbacks1(cm *mkconf.ConfigManager, configName string, cf1 *MyConfig) {
fmt.Printf("Reload config '%v'.\n", configName)
cm.LoadConfig(configName)
cf, err := cm.GetConfig(configName)
if err != nil {
fmt.Printf("Error while reading config: %v\n", err)
return
}
*cf1 = *cf.(*MyConfig)
fmt.Printf("Key : %v\n", cf1.Key)
fmt.Printf("Value : %v\n", cf1.Value)
}
func myCallbacks2(cm *mkconf.ConfigManager, configName string) {
ff := cm.GetChangesForConfig(configName)
for i, v := range ff {
fmt.Printf("Changes №%v %v:\n", i+1, v.Timestamp.Format("02.01.2006 15:04:05.000"))
fmt.Printf("%v: old value: %v new value:%v \n", v.FieldName, v.OldValue, v.NewValue)
}
cm.ClearChangeLogs(configName)
fmt.Println()
fmt.Println()
fmt.Println()
fmt.Println()
}Это демонстрационные функции, которые показывают изменения. Вы можете использовать любой тип.
Функция cm.ClearChangeLogs(configName) является необязательной. По умолчанию весь список изменений сохраняется и не удаляется. Если вам нужно сохранить его - вы можете не очищать его.
На этом шаге начинается асинхронное отслеживание изменений конфигурации. Если произойдет ошибка, она будет отправлена в канал ошибок errChan.
errChan := make(chan error)
go func() {
err := cm.WatchForChanges()
if err != nil {
errChan <- err
}
}()cm.WatchForChanges() автоматически получает сигналы от каналов об изменениях в файле и обновляет журналы изменений. Он запускает обратный вызов, который вы установили заранее. Если он НЕ был установлен, вы получите ошибку.
Reload config 'config'.
Key : da
Value : 9
Changes №1 18.04.2024 10:02:16.981:
key: old value: net new value:da
Reload config 'config'.
Key : ili net
Value : 15
Changes №1 18.04.2024 10:02:26.091:
key: old value: da new value:ili net
Changes №2 18.04.2024 10:02:26.091:
value: old value: 9 new value:15
Здесь мы определяем конфигурационные структуры MyConfig, MyConfig2 и MyConfig3. Для каждой конфигурации создается экземпляр соответствующей структуры. После этого создается фрагмент интерфейсов itf, в который добавляются указатели на ранее созданные экземпляры конфигурации.
cf1 := MyConfig{}
cf2 := MyConfig2{}
cf3 := MyConfig3{}
configPath := "C:\\My saved files\\testConfig"
configNames := []string{"config.json", "config2.json", "config3.xml"}
var itf []interface{}
itf = append(itf, &cf1, &cf2, &cf3)
cm := mkconf.NewConfigManager() Сюда загружаются конфигурации из указанного пути с указанными именами файлов. Каждая конфигурация связана с соответствующим интерфейсом из фрагмента itf.
errors := cm.LoadConfigsFromPath(configPath, configNames, itf)
for _, err := range errors {
if err != nil {
fmt.Printf("error: %v", err)
}
}Функции обратного вызова также можно задать для каждой конфигурации отдельно или для всех сразу. Эта функция назначает один обратный вызов для всех конфигураций. Функция changeCallback будет вызываться при изменении любой из конфигураций.
changeCallback := func(configName string) {
myCallbacksAll1(cm, configName, itf)
}
cm.ChangeCallbackFuncAll(changeCallback)
cm.StartAllChangeMonitoring()func myCallbacksAll1(cm *mkconf.ConfigManager, configName string, cfs []interface{}) {
fmt.Printf("Reload config '%v'.\n", configName)
cm.LoadConfig(configName)
cf, err := cm.GetConfig(configName)
if err != nil {
fmt.Printf("Error while reading config: %v\n", err)
return
}
switch v := cf.(type) {
case *MyConfig:
fmt.Printf("Key : %v\n", v.Key)
fmt.Printf("Value : %v\n", v.Value)
cfs[0] = v
case *MyConfig2:
fmt.Printf("Key : %v\n", v.Key)
fmt.Printf("Value : %v\n", v.Value)
cfs[1] = v
case *MyConfig3:
fmt.Printf("Database : %v\n", v.Database)
fmt.Printf("Logging : %v\n", v.Logging)
fmt.Printf("ServerInfo : %v\n", v.ServerInfo)
cfs[2] = v
default:
fmt.Printf("hz cho za tip")
}
}Это тестовый общий обратный вызов. Это пример вывода и обновления измененного конфига.
В примере используются следующие конфигурации:
type MyConfig struct {
Key string `json:"key"`
Value int `json:"value"`
}
type MyConfig2 struct {
Key string `yaml:"key"`
Value string `yaml:"value"`
}
type MyConfig3 struct {
XMLName xml.Name `xml:"config"`
ServerInfo ServerInfo `xml:"server_info"`
Database Database `xml:"database"`
Logging Logging `xml:"logging"`
}
type ServerInfo struct {
Host string `xml:"host"`
Port int `xml:"port"`
}
type Database struct {
DatabaseName string `xml:"database_name"`
User string `xml:"user"`
Password string `xml:"password"`
}
type Logging struct {
Level string `xml:"level"`
Output string `xml:"output"`
}На этом шаге начинается асинхронное отслеживание изменений конфигурации. Если произойдет ошибка, она будет отправлена в канал ошибок errChan.
errChan := make(chan error)
go func() {
err := cm.WatchForChanges()
if err != nil {
errChan <- err
}
}()cm.WatchForChanges() автоматически получает сигналы от каналов об изменениях в файле и обновляет журналы изменений. Он запускает обратный вызов, который вы установили заранее. Если он НЕ был установлен, вы получите ошибку.
Reload config 'config'.
Key : a)))
Value : 15
Reload config 'config2'.
Key : hi.
Value : !!!
Reload config 'config3'.
Database : {my_database admin secretpassword}
Logging : {info logs/app.log}
ServerInfo : {example.ua.com 8080}