在Node.js中,我使用nconf模块为每个项目提供环境变量,如S3键,GCM键等。
我无法在Go中找到类似的解决方案。
有哪些普遍接受的工具可以帮助管理每个Go项目的环境变量?
提前致谢。
答案 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