Skip to content

Example RU

SHEP4RDO edited this page Apr 18, 2024 · 2 revisions

Использование модуля mkconf

Пример использования одного конфига

Инициализация

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}