Перейти к содержимому
ГоМастер

Поиск по урокам

Найдите урок, курс, термин или раздел

viper или envconfig: как читать конфигурацию в Go

envconfig — минимализм 12-factor: одни переменные окружения, теги над структурой, ноль файлов и зависимостей. viper — полный конвейер: YAML и TOML, окружение, флаги и KV-хранилища с приоритетами, watch и перечитка на живом сервисе.

envconfigviperкурс

Подбор под ваши приоритеты

Двигайте ползунки — насколько для вас важен каждый критерий (0 — не важен, 5 — критично). Счёт пересчитывается на лету: это взвешенное среднее оценок библиотек по критериям, а не бенчмарк.

Файлы, окружение, флаги, KV-хранилища

YAML, TOML, JSON и другие

Unmarshal в структуры с проверкой

Watch, перечитка без перезапуска

Зависимости, порог входа, предсказуемость

Взвешенный счёт

  • viperваш матч84
  • envconfig52

Под ваши веса лидирует viper: продуктам с файловым конфигом, профилями окружений и требованием перечитки без перезапуска.

Вопрос «viper или envconfig» встаёт, когда в проекте появляется первый настоящий конфиг: порт, строка подключения, уровень логов. Обе библиотеки собирают значения в структуру и избавляют от ручного os.Getenv, но масштаб у них разный. envconfig решает ровно одну задачу: читает переменные окружения с префиксом и тегами в поля структуры — двенадцать строк, ноль файлов, идеал 12-factor. viper — это конвейер конфигурации: файлы YAML, TOML и JSON, окружение, флаги cobra, удалённые KV-хранилища и явные приоритеты между источниками, плюс watch для перечитки без перезапуска. На этой странице сравним оба по одним критериям, покажем одну и ту же задачу — конфиг HTTP-сервиса — рядом и соберём персональную рекомендацию ползунками.

envconfig силён предсказуемой простотой: структура с тегами envconfig, вызов process — и все значения уже в полях с проверкой типов. Ошибки честные: нет переменной или не распарсилось — процесс падает со списком проблем ещё на старте, а не в проде на третьем запросе. Вес и зависимости минимальные, код читается без документации. Расплата — один источник: файлы не читаются вовсе, приоритетов между слоями нет, а значения по умолчанию живут в коде тегами; как только появляется второй источник — YAML для локальной разработки, например, — envconfig приходится обкладывать ручным кодом.

viper отвечает за полный жизненный цикл конфигурации: ReadInConfig читает YAML или TOML, AutomaticEnv с префиксом подмешивает окружение поверх файла, флаги cobra встают ещё одним слоем, а порядок источников фиксируется явно — флаги выше окружения, окружение выше файла. Unmarshal собирает всё в те же структуры, WatchConfig и OnConfigChange перечитывают файл на живом процессе, а для секретов есть интеграция с vault и KV-хранилищами. Цена — вес и поверхность API: зависимость тянет десятки форматов и провайдеров, часть ловушек вроде регистрации env-ключей до чтения файла надо знать, а новичок читает документацию, прежде чем понять, откуда возьмётся значение.

Как читать итог ниже: оценки — усреднение практики команды проекта, а не замеры; ползунки подставляют ваши приоритеты. Грубая граница: контейнерный сервис, где всё приходит из окружения, и хочется лёгкости — envconfig; продукт с YAML-конфигом, профилями и перезагрузкой без рестарта — viper. Между ними стоит и третий путь: koanf — конвейер полегче viper, о нём отдельная страница сравнения. А полный путь viper разобран в нашем курсе — от первого YAML до секретов и тестирования конфигов.

Одна и та же задача в каждой библиотеке

Задача-эталон для этого сравнения: посмотрите на разницу в церемониях, типах и обработке ошибок — так выбор ощущается, а не только описывается словами.

Окружение в структуру: один вызов process и ноль лишних зависимостей

package main

import (
  "fmt"
  "log"

  "github.com/kelseyhightower/envconfig"
)

type Config struct {
  Port    int    `envconfig:"PORT" default:"8080"`
  DBURL   string `envconfig:"DB_URL" required:"true"`
  Debug   bool   `envconfig:"DEBUG"`
}

func main() {
  var cfg Config
  // APP_PORT, APP_DB_URL, APP_DEBUG -> поля структуры
  err := envconfig.Process("app", &cfg)
  if err != nil {
    log.Fatal(err)
  }
  fmt.Println(cfg.Port, cfg.DBURL, cfg.Debug)
}

Сильные и слабые стороны

envconfig

Окружение в структуру: один вызов process и ноль лишних зависимостей

  • Минимализм: тег над полем и вызов process — вся настройка, код читается без документации
  • Идеал 12-factor: конфиг только из окружения — контейнеры, Compose и Kubernetes довольны
  • Честные ошибки старта: нет переменной или не распарсилось — процесс падает со списком сразу
  • Один источник: файлы YAML и TOML не читаются вовсе — второй слой собирается руками
  • Никаких приоритетов: флаги, файлы и окружение между собой миксовать нечем
  • Watch нет: изменения подхватываются только перезапуском процесса

Берите, если: контейнерным сервисам и cli, где конфиг — это переменные окружения, а вес зависимостей важен.

viper

Полный конвейер: файлы, окружение и флаги с явными приоритетами

  • Слои источников: YAML и TOML, окружение с префиксом, флаги cobra — порядок фиксируется явно
  • Unmarshal в структуры: значения из всех слоёв собираются в один типизированный конфиг
  • WatchConfig: файл перечитывается на живом процессе, OnConfigChange поднимает колбек
  • Вес и поверхность: зависимость тянет десятки форматов и провайдеров ради пары нужных
  • Ловушки API: env-ключи регистрируются до чтения файла, префиксы и замены — отдельная наука
  • Строгой типизации нет: GetString и GetInt возвращают значения без проверки схемы

Берите, если: продуктам с файловым конфигом, профилями окружений и требованием перечитки без перезапуска.

Оценки по критериям

Шкала 1-5: экспертная оценка команды проекта по практике, а не синтетика.

Сравнение envconfig, viper по критериям
Критерийenvconfigviper
Источники значенийФайлы, окружение, флаги, KV-хранилища
Форматы файловYAML, TOML, JSON и другие
Структуры и типыUnmarshal в структуры с проверкой
Динамика в рантаймеWatch, перечитка без перезапуска
Простота и весЗависимости, порог входа, предсказуемость

Вердикт: когда что выбирать

envconfig закрывает одну задачу идеально — окружение в структуру с проверкой на старте. viper закрывает весь жизненный цикл конфигурации — слои источников, приоритеты и перечитку. Выбирайте по числу источников, а не по звёздам на GitHub.

12-factor-сервис: контейнер, всё из переменных окруженияenvconfigОдин вызов process, честные ошибки старта, ноль лишнего веса
YAML-файл плюс окружение плюс флаги с приоритетамиviperСлои источников и порядок явные — значение предсказуемо
Конфиг меняется без перезапуска сервисаviperWatchConfig и OnConfigChange перечитывают файл на живом процессе
Конвейер конфигов нужен, но viper кажется тяжёлымkoanfПохожая модель слоёв полегче — есть отдельное сравнение

А что выбрали вы?

Кликните по своему выбору — голос сохранится только в вашем браузере (персональные данные никуда не отправляются).

Частые вопросы

Что легче по зависимостям — viper или envconfig?

envconfig крошечный: одна библиотека без транзитивных зависимостей — она не тянет парсеры форматов и драйверы хранилищ. viper заметно тяжелее: ради YAML, TOML, remote-KV и флагов он привносит приличный граф зависимостей, что видно в go.mod после первого импорта. Для маленького CLI или edge-сервиса разница существенна; для большого backend-приложения вес viper уже не решает, а возможности окупаются.

Умеет ли envconfig читать YAML-файлы?

Нет — envconfig работает только с переменными окружения, это принципиальная часть его дизайна. Если нужен файл, его читают отдельно: распарсивают YAML в структуру, а потом переносят значения в переменные окружения или прямо в поля конфига, разруливая приоритет руками. Именно эту рутину с слоями и приоритетами и снимает viper — поэтому связка файл плюс окружение обычно и приводит команды к нему.

Как подхватывать изменения конфига без перезапуска?

Из пары contenders это умеет только viper: WatchConfig следит за файлом конфига, а колбек OnConfigChange срабатывает на изменение — внутри обычно перечитывают значения и обновляют живые настройки, например уровень логов. В Kubernetes-мире альтернативный путь — перезапуск пода с новым ConfigMap, тогда динамика не нужна, и простой envconfig снова смотрится выигрышно за счёт простоты.

А если нужны только переменные окружения — нужна ли вообще библиотека?

Для пары значений хватит os.Getenv с ручной конвертацией типов. Библиотека окупается, когда переменных больше десятка: envconfig даёт теги, значения по умолчанию, required-проверку и аккуратные ошибки старта вместо молчаливых пустых строк. Отдельный бонус — единое место, где перечислен весь конфиг сервиса: структура становится документацией, которую новые разработчики читают вместо расспросов в чате.

Другие сравнения