组织环境变量Golang

时间:2014-07-21 20:15:02

标签: go environment-variables

在Node.js中,我使用nconf模块为每个项目提供环境变量,如S3键,GCM键等。

我无法在Go中找到类似的解决方案。

有哪些普遍接受的工具可以帮助管理每个Go项目的环境变量?

提前致谢。

4 个答案:

答案 0 :(得分:25)

我强烈建议您使用github.com/namsral/flag。 它与built in 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

当提供命令行参数很难时,这可能很重要。例如,如果使用gin自动重新启动服务器,则无法提供命令行参数,因为gin只是在主代码上调用go run而没有传递任何参数。

答案 1 :(得分:10)

在我开始使用Go的过程中,我对此做了一些阅读。根据此链接http://peter.bourgon.org/go-in-production/,他们建议使用CLI标志(参数)而不是环境变量 - 他们甚至将环境变量转换为其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:root@tcp(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 “该参数究竟是什么?”为您提供完整的文档:

admin@dev01:~/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:root@tcp(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上有很多选项,并且不需要文档 - 它内置于flags包中。

您可以立即清楚地看到默认值。

使用这种类型的文档,我倾向于设置团队使用的常见“开发环境”的所有默认值。我们都有对本地数据库的root / root访问权限。我们都在开发期间使用端口8080用于此特定Web应用程序等。这样,您只需运行:

go build
./wwwgo

应用程序运行所有默认值 - 记录的默认值。在生产中,只需覆盖默认值。如果任何参数格式错误,内置标志解析器会使应用程序感到恐慌,这也非常好。

答案 2 :(得分:3)

我们已将其用于大规模微服务应用程序。这不涉及任何第三方库的使用,只是使用反射来简单地进行lang编写。它非常易于使用,并遵循DRY原理。添加新的环境变量和配置默认值非常容易。您还可以通过仅更改两行代码来将配置文件的加载设置为后备。检出github页以获取更多信息。

package config

import (
    "fmt"
    "os"
    "reflect"
)

/* Tag names to load configuration from environment variable */
const (
    ENV     = "env"
    DEFAULT = "default"
)

type Configuration struct {
    Port        string `env:"port" default:"3009"`
    MongoURL    string `env:"MongoUrl" default:"mongodb://localhost:27017/test"`
    UserService string `env:"UserService" default:"http://localhost:3005"`
    AuthService string `env:"AuthService" default:"http://localhost:3050"`
    Debug       string `env:"Debug" default:"true"`
}

/* Non-exported instance to avoid accidental overwrite */
var serviceConfig Configuration

func setConfig() {
    // ValueOf returns a Value representing the run-time data
    v := reflect.ValueOf(serviceConfig)
    for i := 0; i < v.NumField(); i++ {
        // Get the field tag value
        tag := v.Type().Field(i).Tag.Get(ENV)
        defaultTag := v.Type().Field(i).Tag.Get(DEFAULT)

        // Skip if tag is not defined or ignored
        if tag == "" || tag == "-" {
            continue
        }
        a := reflect.Indirect(reflect.ValueOf(serviceConfig))
        EnvVar, Info := loadFromEnv(tag, defaultTag)
        if Info != "" {
            fmt.Println("Missing environment configuration for '" + a.Type().Field(i).Name + "', Loading default setting!")
        }
        /* Set the value in the environment variable to the respective struct field */
        reflect.ValueOf(&serviceConfig).Elem().Field(i).SetString(EnvVar)
    }
}

func loadFromEnv(tag string, defaultTag string) (string, string) {
    /* Check if the tag is defined in the environment or else replace with default value */
    envVar := os.Getenv(tag)
    if envVar == "" {
        envVar = defaultTag
        /* '1' is used to indicate that default value is being loaded */
        return envVar, "1"
    }
    return envVar, ""
}

/*GetConfiguration :Exported function to return a copy of the configuration instance */
func GetConfiguration() Configuration {
    return serviceConfig
}

func init() {
    setConfig()
    fmt.Printf("Service configuration : %+v\n ", serviceConfig)
}

答案 3 :(得分:1)

我更喜欢用 go-arg 来设置环境变量。它易于使用且具有很好的功能。

例如:


package configs

import (
    "fmt"
    "github.com/alexflint/go-arg"
)

type config struct {
     DBHost string `arg:"env:DBHost, -D, --dbhost" help:"Host of the database" placeholder:"DBHost"`
}

var Config config

func main(){

  arg.MustParse(&Config)
  fmt.Println(Config.DBHost)

}

使用这个库,您可以从环境中获取变量,也可以通过参数传递。

export DBHost=127.0.0.1

go run ./main.go --dbhost=127.0.0.1