Как в Go-проектах принято управлять различными окружениями (development, staging, production)?

Ответ

Управление конфигурацией для разных окружений — ключевая задача в разработке. В Go для этого используют несколько подходов:

  1. Переменные окружения: Самый простой и популярный способ, соответствующий принципам 12-factor app. Для чтения используется стандартный пакет os.

    // Пример чтения переменной окружения с fallback-значением
    dbHost := os.Getenv("DB_HOST")
    if dbHost == "" {
        dbHost = "localhost" // Значение по умолчанию для dev-окружения
    }
  2. Файлы .env: Для удобства локальной разработки переменные окружения хранят в .env файлах и загружают их с помощью библиотек, например, github.com/joho/godotenv.

  3. Конфигурационные файлы (YAML, JSON, TOML): Для сложных конфигураций используют файлы. Популярная библиотека github.com/spf13/viper умеет читать конфиги из файлов, переменных окружения, флагов и удаленных хранилищ (etcd, Consul), что делает ее очень гибкой.

  4. Флаги командной строки: Для простых переключателей (например, -env=production) используется стандартный пакет flag.

Лучшая практика: Комбинировать подходы. Например, использовать Viper для чтения конфигурации из файла (config.yaml), но позволять переопределять любые параметры через переменные окружения. Это обеспечивает гибкость как для локальной разработки, так и для развертывания в Docker/Kubernetes, где управление через переменные окружения является стандартом.

Ответ 18+ 🔞

Так, слушай сюда, про конфиги в Go. Это ж святое, блядь! Без них — никуда, а с ними — вечная головная боль, где их хранить, чтобы не охуеть потом при деплое.

Ну, первое и самое простое — переменные окружения. Это как священное писание для любого уважающего себя приложения, особенно если ты хоть раз слышал про эти твои 12-factor app. В Go за это отвечает стандартный пакет os, и там всё до безобразия просто.

// Берём переменную из окружения, а если её нет — подставляем дефолт для локалки
dbHost := os.Getenv("DB_HOST")
if dbHost == "" {
    dbHost = "localhost" // Ну а хули, на своей машине-то можно
}

Но вот проблема, ёпта: на локальной машине эти переменные окружения — их же дохуя набивать вручную! Для этого и придумали файлы .env. Кинул файлик в проект, прописал там DB_HOST=localhost, и никакой тебе головной боли. Загрузить их помогает, например, библиотека github.com/joho/godotenv. Удобно, сука, как швейцарские часы.

А если конфигурация разрослась до невъебенных масштабов? Там и базы, и редисы, и ключи API, и ещё какая-то хуйня? Тогда уже пора тянуть конфигурационные файлы в YAML, JSON или TOML. И тут на сцену выходит github.com/spf13/viper — это вообще, блядь, швейцарский нож в мире конфигов. Он умеет читать из файлов, из переменных окружения, из флагов командной строки и даже из удалённых хранилищ вроде etcd. Гибкость — овердохуищная.

Ну и для совсем простых случаев, когда нужно просто переключить окружение, сгодятся флаги командной строки через стандартный flag. Типа -env=production, и поехали.

А теперь главное, блядь, слушай! Лучшая практика — это всё смешать в одну кучу, но сделать это элегантно. Берёшь того же Viper, настраиваешь чтение из config.yaml. А потом, если какая-то переменная окружения совпадает по имени с ключом из конфига — Viper её переопределит! Это гениально, ёпта. На локалке работаешь с файлом, а в продакшене, в том же Kubernetes, где всё через переменные окружения забивается, — просто накидываешь их поверх, и ни один файл конфига менять не надо. Красота, в рот меня чих-пых!