Организация переменных среды Golang

В Node.js Я использую модуль nconf для размещения переменных среды, таких как ключи S3, ключи GCM и т.д. для каждого из моих проектов.

Мне не удалось найти подобное решение в Go.

Каковы общепринятые инструменты для управления переменными среды для каждого проекта Go?

Спасибо заранее.

Ответ 1

Я немного читал об этом некоторое время назад, когда я начинал работу с Go. Согласно этой ссылке http://peter.bourgon.org/go-in-production/, они рекомендуют использовать флаги (параметры) CLI вместо окружения vars - они даже конвертируют окружения vars в флаги в свои CLI.

Потребовалось некоторое привыкание; но я действительно вижу преимущества перехода чистых флагов CLI между средами разработки, промежуточной и производственной среды - с конкретными сценариями для каждой среды.

Например, здесь небольшое веб-приложение, которое я написал недавно:

// global flags
var isdebug bool
var port int
var cert string
var key string
var dbdsn string
var dbmaxidle int
var dbmaxopen int
var imguri string

// init is the entry point for the entire web application.
func init() {

    log.Println("Starting wwwgo ...")

    // setup the flags
    //flag.StringVar(&host, "host", "", "Specify a host to redirect to. Use this to redirect all traffic to a single url.")
    flag.IntVar(&port, "port", 8080, "Specify the port to listen to.")
    flag.BoolVar(&isdebug, "isdebug", false, "Set to true to run the app in debug mode.  In debug, it may panic on some errors.")
    flag.StringVar(&cert, "cert", "", "Enables listening on 443 with -cert and -key files specified.  This must be a full path to the certificate .pem file. See http://golang.org/pkg/net/http/#ListenAndServeTLS for more information.")
    flag.StringVar(&key, "key", "", "Enables listening on 443 with -cert and -key files specified.  This must be a full path to the key .pem file. See http://golang.org/pkg/net/http/#ListenAndServeTLS for more information.")
    flag.StringVar(&dbdsn, "dbdsn", "root:[email protected](localhost:3306)/dev_db?timeout=5s&tls=false&autocommit=true", "Specifies the MySql DSN connection.")
    flag.IntVar(&dbmaxidle, "dbmaxidle", 0, "Sets the database/sql MaxIdleConns.")
    flag.IntVar(&dbmaxopen, "dbmaxopen", 500, "Sets the database/sql MaxOpenConns.")
    flag.StringVar(&imguri, "imguri", "/cdn/uploads/", "Set this to the full base uri of all images, for example on a remote CDN server or local relative virtual directory.")
    flag.Parse()

    // log our flags
    if isdebug != false {
        log.Println("DEBUG mode enabled")
    }
    if cert != "" && key != "" {
        log.Println("Attempting SSL binding with supplied cert and key.")
    }
    if dbdsn != "" {
        log.Printf("Using default dbdsn: %s", dbdsn)
    }

    ...
}

Это действительно становится приятным в промежуточных/производственных средах.

Быстрый ./wwwgo -h для "какой черт был этот параметр?" дает полную документацию:

[email protected]:~/code/frontend/src/wwwgo [master]$ ./wwwgo -h
Usage of ./wwwgo:
  -cert="": Enables listening on 443 with -cert and -key files specified.  This must be a full path to the certificate .pem file. See http://golang.org/pkg/net/http/#ListenAndServeTLS for more information.
  -dbdsn="root:[email protected](localhost:3306)/dev_db?timeout=5s&tls=false&autocommit=true": Specifies the MySql DSN connection.
  -dbmaxidle=0: Sets the database/sql MaxIdleConns.
  -dbmaxopen=500: Sets the database/sql MaxOpenConns.
  -imguri="/cdn/uploads/": Set this to the full base uri of all images, for example on a remote CDN server or local relative virtual directory.
  -isdebug=false: Set to true to run the app in debug mode.  In debug, it may panic on some errors.
  -key="": Enables listening on 443 with -cert and -key files specified.  This must be a full path to the key .pem file. See http://golang.org/pkg/net/http/#ListenAndServeTLS for more information.
  -port=8080: Specify the port to listen to.

Очень приятно иметь много опций в CLI, и никакой документации не требуется - она ​​встроена в пакет флагов.

Вы можете сразу увидеть значения по умолчанию.

При таком типе документации я стараюсь установить все значения по умолчанию для общих "сред разработки", которые использует команда. У всех нас есть доступ root/root к нашим локальным базам данных. Мы все используем порт 8080 для этого конкретного веб-приложения во время разработки и т.д. Таким образом, вам просто нужно запустить:

go build
./wwwgo

И приложение работает со всеми значениями по умолчанию - значениями по умолчанию, которые документированы. В производстве просто переопределите значения по умолчанию. Встроенные анализаторы пакетов будут паниковать приложение, если какие-либо параметры находятся в неправильном формате, что тоже очень приятно.

Ответ 2

Я бы настоятельно рекомендовал вместо этого использовать github.com/namsral/flag. Это как встроенный флаг, за исключением того, что вы можете также поставлять параметры через переменные среды.

Например, предположим, что у вас есть этот код:

package main

import "fmt"
import "github.com/namsral/flag"

func main() {
    var port = 3000
    flag.IntVar(&port, "port", port, "Port number")
    flag.Parse()
    fmt.Println("You seem to prefer", port)
}

Затем вы можете указать значения с помощью параметра командной строки или переменной среды:

:~/dev/GO$ go run dummy.go
You seem to prefer 3000
:~/dev/GO$ go run dummy.go -port=1234
You seem to prefer 1234
:~/dev/GO$ PORT=4321 go run dummy.go
You seem to prefer 4321
:~/dev/GO$ PORT=4321 go run dummy.go -port=5555
You seem to prefer 5555

Это может иметь значение, когда трудно предоставить командные строки args. Например, если вы используете gin для автоматического перезапуска сервера, у вас нет способа предоставить аргументы командной строки, так как gin просто вызывает go run на главной кода без каких-либо аргументов.