人権真骨頂

とくがたかいことでゆうめい

Golangで環境変数をシュッっと良い感じに扱う

はじめに

この記事は,Aizu Advent Calendar 2016の5日目の記事.

www.adventar.org

前の記事は, id:mic_psm

micpsm.hatenablog.com

です.自分も最近新型MacBookPro に変えてハッピー. 明日の記事は未定なので,書いてくれ!!!!!

本題

Golangで環境変数を扱うとき,普通はosパッケージを利用してこんな感じで扱うと思う.

port := os.Getenv("PORT")

だけど,大量の環境変数を扱うときとかダルかったりそもそも構造体によしなに入って欲しいかったり,よしなに型が付いて欲しいですね〜みたいな気持ちになる.

そこで,このライブラリを使うと良い感じになる.

github.com

例えば,以下のような設定を環境変数から読みたいとする.

  • PORT
    • int
  • DEBUG
    • bool
    • default false
  • TIMEOUT
    • time.Duration

普通にやるとこんな感じになる.

portStr := os.Getenv("PORT")
port, _ := strconv.Atoi(portStr)

debug := false
debugStr := os.Getenv("DEBUG")
if debugStr == "true" {    
    debug = true
}

timeoutStr := os.Getenv("TIMEOUT")
timeout, _ := strconv.Atoi(timeoutStr)
timeoutDuration := time.Duration(timeout)

envconfigを使うと以下のように書ける.

type Config struct {    
    Port int
    Debug bool
    Timeout time.Duration
}

func main() {
    var config Config
    envconfig.Process("", &config)
}

これで, Config の構造体の中にちゃんと環境変数で設定したやつが入る.

タグアノテーションを使って細かい設定もできる.

type Config struct {    
    Port int `required:"true"` // 設定されていないとエラーが発生する
    Debug bool `default:"true"` // デフォルト値としてtrueが設定される
    Timeout time.Duration `envconfig:"TIME_OUT"` // 設定しないと "TIMEOUT" で読まれる
}

他にも最近追加された機能として,構造体の埋め込みができる. 例えば,以下の様なことができる.

type Config struct {    
    Port int
    Debug bool
    Timeout time.Duration
    MySQL MySQL `envconfig:"MYSQL"`    
    Redis Redis
}

type MySQL struct {    
    Port int
    Host string
    User string
    Database string
}

type Redis struct {
    Port int
    Host string
}

func main() {
    var config Config
    envconfig.Process("APP", &config)
}

こうすると, APP_MYSQL_PORT っていう環境変数に config.MySQL.Port でアクセスすることができるようになって便利.

有名なライブラリだけど,便利なので紹介した.もっと良いやつがあればぜひ教えて欲しい.