## 读取和设置环境变量 除了读取文件和命令行传递参数外,环境变量是另一个向应用传递参数的方式。本文将简单探讨如何获取和操作基本的环境变量,然后我们一起来看看如何结合第三方库[https://github.com/kelseyhightower/envconfig](https://github.com/kelseyhightower/envconfig)(Star 1741)来使用。 我们将构建一个可以通过JSON或环境变量读取配置的应用程序。下一章节将进一步探索其他替代格式,包括TOML和YAML。 ### 实践 1. 创建config.go: ``` package envvar import ( "encoding/json" "os" "github.com/kelseyhightower/envconfig" "github.com/pkg/errors" ) // LoadConfig将从存储在路径中的json文件中选择加载文件, // 然后根据envconfig struct标记覆盖这些值。 // envPrefix是我们为环境变量添加的前缀。 func LoadConfig(path, envPrefix string, config interface{}) error { if path != "" { err := LoadFile(path, config) if err != nil { return errors.Wrap(err, "error loading config from file") } } // envconfig.Process根据环境变量填充指定的结构 err := envconfig.Process(envPrefix, config) return errors.Wrap(err, "error loading config from env") } // LoadFile 解析一个json文件并填充到config中 func LoadFile(path string, config interface{}) error { configFile, err := os.Open(path) if err != nil { return errors.Wrap(err, "failed to read config file") } defer configFile.Close() decoder := json.NewDecoder(configFile) if err = decoder.Decode(config); err != nil { return errors.Wrap(err, "failed to decode config file") } return nil } ``` 2. 创建main.go: ``` package main import ( "bytes" "fmt" "io/ioutil" "os" "myConcurrency/chapter2/envvar" ) // Config 将保存我们从json文件和环境变量中捕获的配置 type Config struct { Version string `json:"version" required:"true"` IsSafe bool `json:"is_safe" default:"true"` Secret string `json:"secret"` } func main() { var err error // 建立一个临时json配置文件 tf, err := ioutil.TempFile("", "tmp") if err != nil { panic(err) } defer tf.Close() defer os.Remove(tf.Name()) // json 配置文件的内容 secrets := `{ "secret": "so so secret" }` if _, err = tf.Write(bytes.NewBufferString(secrets).Bytes()); err != nil { panic(err) } // 向环境变量中添加变量及对应值 if err = os.Setenv("EXAMPLE_VERSION", "1.0.0"); err != nil { panic(err) } if err = os.Setenv("EXAMPLE_ISSAFE", "false"); err != nil { panic(err) } c := Config{} // 从文件中读取配置参数 if err = envvar.LoadConfig(tf.Name(), "EXAMPLE", &c); err != nil { panic(err) } fmt.Println("secrets file contains =", secrets) // 获取环境变量参数及对应值 fmt.Println("EXAMPLE_VERSION =", os.Getenv("EXAMPLE_VERSION")) fmt.Println("EXAMPLE_ISSAFE =", os.Getenv("EXAMPLE_ISSAFE")) // c既保存了json配置文件的参数也保存了环境变量的参数 我们将其打印 fmt.Printf("Final Config: %#v\n", c) } ``` 3. 运行main.go,这会输出: ``` secrets file contains = { "secret": "so so secret" } EXAMPLE_VERSION = 1.0.0 EXAMPLE_ISSAFE = false Final Config: main.Config{Version:"1.0.0", IsSafe:false, Secret:"so so secret"} ``` ### 说明 使用os包可以很容易的设置和读取环境变量。第三方库envconfig使用结构体tag将环境变量映射给结构体的方式很巧妙,有兴趣可以阅读其源码。 LoadConfig函数可以从各种来源获取配置信息,而不会产生大量开销或太多额外的依赖关系值得借鉴。 另外,请注意错误的处理。在此章节中使用errors.Wrap来生成错误,以便我们可以在不丢失原始错误信息的情况下注释错误。有关详细信息,请参阅第4章“错误处理“。 * * * * 学识浅薄,错误在所难免。欢迎在群中就本书提出修改意见,以飨后来者,长风拜谢。 Golang中国(211938256) beego实战(258969317) Go实践(386056972)