Редкая программа обходится без файла конфигурации. Даже если вы пишите простенький REST-сервис , то ему как минимум нужно знать, какой порт и на каком интерфейсе слушать, а также где искать PostgreSQL . Что уж говорить о более сложных приложениях. Для чтения конфигов в проектах на Go часто используют библиотеку spf13/viper.
Почему Viper ? Потому что он умеет очень много всего:
- Поддерживаются форматы Yaml, Json, INI и другие;
- Параметры конфигурации можно переопределять через флаги ;
- Также параметры можно задавать через переменные окружения, как это принято в Kubernetes ;
- Viper умеет забирать параметры из etcd и Consul ;
- Параметры можно менять на лету, что позволяет изменить поведение программы без перезапуска;
Другими словами, какие бы требования не предъявлялись к приложению, Viper почти наверняка сможет их удовлетворить. Вот все им и пользуются.
Все возможности библиотеки мы рассматривать не будем, так как их много и получится пересказ документации. Рассмотрим только самый базовый пример использования, который обычно и нужен:
customFormatter := new ( log . TextFormatter )
customFormatter . TimestampFormat = «2006-01-02 15:04:05»
customFormatter . FullTimestamp = true
log . SetFormatter ( customFormatter )
viper . AutomaticEnv ()
viper . SetEnvKeyReplacer ( strings . NewReplacer ( «.» , «_» ))
viper . SetEnvPrefix ( «restexample» )
viper . SetDefault ( «loglevel» , «debug» )
viper . SetDefault ( «listen» , «localhost:8080» )
viper . SetDefault ( «db.url» , «postgres://localhost» )
if configPath != «» {
log . Infof ( «Parsing config: %s» , configPath )
viper . SetConfigFile ( configPath )
err := viper . ReadInConfig ()
if err != nil {
log . Panicf ( «Unable to read config file: %s» , err )
}
} else {
log . Infof ( «Config file is not specified.» )
}
logLevelString := viper . GetString ( «loglevel» )
logLevel , err := log . ParseLevel ( logLevelString )
if err != nil {
log . Panicf ( «Unable to parse loglevel: %s» , logLevelString )
}
log . SetLevel ( logLevel )
log . Infof ( «Listen: %s» , viper . GetString ( «listen» ))
log . Infof ( «DB URL: %s» , viper . GetString ( «db.url» ))
}
Путь до файла конфигурации передается приложению при помощи обязательного флага --config
или его синонима -c
, как это ранее было описано в посте Парсинг флагов и аргументов в языке Go .
Пример файла конфигурации:
listen : 0.0.0.0: 8080
db :
url : postgres://postgresql@localhost/restservice
Варианты запуска приложения:
Config file is not specified.
Listen: localhost:8080
DB URL: postgres://localhost
$ ./rest -c ./config.yaml
Parsing config: ./config.yaml
Listen: 0.0.0.0:8080
DB URL: postgres://restservice@localhost/restservice
$ RESTEXAMPLE_LISTEN=localhost:80 ./rest -c ./config.yaml
Parsing config: ./config.yaml
Listen: localhost:80
DB URL: postgres://restservice@localhost/restservice
$ RESTEXAMPLE_LISTEN=localhost:80 ./rest
Config file is not specified.
Listen: localhost:80
DB URL: postgres://localhost
В выводе опущены таймстемпы, так как они нам сейчас не интересны.
Первый вариант демонстрирует запуск без указания файла конфигурации и каких-либо переменных окружения. В этом случае используются параметры по умолчанию, указанные в коде. Если указать файл конфигурации, как во втором варианте, то параметры из файла перезатрут параметры по умолчанию. Наконец, третий и четвертый варианты запуска демонстрируют, что переменные окружения имеют приоритет как перед параметрами по умолчанию, так и перед параметрами из файла конфигурации.
Как видите, ничего сложного! Наиболее полную и актуальную информацию, как обычно, вы найдете в официальной документации .