見出し画像

【Go初学】設定ファイル、環境変数から設定情報を取得する

概要

プロジェクトを構成する定数をアプリ内に埋め込まず、環境によって切り替えられるよう外部ファイルとして設定しておきたい。さらにその中でもパスワードなど外部非公開にしたい秘匿情報は、より公開リスクを少なくするため環境変数へ設定し、設定情報を取得する。

アプリケーションは時に設定を定数としてコード内に格納する。これはTwelve-Factorに違反している。Twelve-Factorは 設定をコードから厳密に分離すること を要求する。設定はデプロイごとに大きく異なるが、コードはそうではない。

THE TWELVE-Factor App III. 設定

設定ファイル情報の取得

データを簡易に扱いやすいymlファイルを設定ファイルとする。設定ファイルも間違いが起こりにくいよう書きやすさや読みやすさが大事。他にJSONやiniファイルもあるが、書き方がちょっと面倒だったり、Windows系ファイルのようだったりする。

▼ymlファイルの作成
プロジェクトのsrc下などに配置。配列やネスト構造でなければ単にコロン区切りで「キー名:値」とするだけでよい。

# config.ymlenvironment: develop

sqldriver: mysql
user: testuser
password: testpassword
protocol: tcp
address: 127.0.0.1:3306
database: TestDatabase

▼ymlファイルデータの取得
標準パッケージの io/ioutil を利用。名前の通りファイルの入出力 I/O の便利に扱う機能を揃えたパッケージ。
Example の通りファイルへのパスを渡して取得する。

content, err := ioutil.ReadFile("config.yml")

▼yml構造の文字列から構造体へのマッピング
go-yaml/yaml パッケージが主流のようなのでこちらを使ってみる。v3もあるがv2のimport数が圧倒的に大きい、最終更新も去年で古くなく枯れている方が問題が少ないだろうとv2選択。

// プロジェクト内の必要なパッケージ上で実行してパッケージ取得
$ go get gopkg.in/yaml.v2

Example にある通り、必要なものは「ymlファイルの文字列をbyte配列にしたもの」「マッピングする構造体のポインタ」。文字列は先ほど ioutil で取得したものを渡す。

err := yaml.Unmarshal([]byte(content), &t)

マッピングする構造体の方で、フィールドに対応するキー名を記述する。

type Config struct {
  Environment string `yaml:"environment"`

  SqlDriver string `yaml:"sqldriver"`
  User      string `yaml:"user"`
  Password  string `yaml:"password"`
  Address   string `yaml:"address"`
  DataBase  string `yaml:"database"`
}

以上を関数化し、引数でファイルパスを渡すようにする。

package main

import (
  "fmt"
  "io/ioutil"

  "gopkg.in/yaml.v2"
)

func main() {
  config, err := LoadConfig("config.yml")
  if err != nil {
    panic(err)
  }

  fmt.Printf("config: %v\n", config)
}

// 設定ファイルを読み込む
func LoadConfig(filePath string) (config *Config, err error) {
  content, err := ioutil.ReadFile(filePath)
  if err != nil {
    return nil, err
  }

  result := &Config{}
  if err := yaml.Unmarshal(content, result); err != nil {
    return nil, err
  }

  return result, nil
}

type Config struct {
  Environment string `yaml:"environment"`

  SqlDriver string `yaml:"sqldriver"`
  User      string `yaml:"user"`
  Password  string `yaml:"password"`
  Address   string `yaml:"address"`
  DataBase  string `yaml:"database"`
}
$ go run main.go
config: &{develop mysql testuser testpassword 127.0.0.1:3306 TestDatabase}

環境変数から設定情報の取得

こちらのリンクを参考にした。ExpandEnv() を使いyml構造の文字列を環境変数の値で置き換えたのち、構造体へマッピングする。

content = []byte(os.ExpandEnv(string(content)))

環境変数はシェル上で export しておくか、~/.bash_profileなどに書き込んでおき、プロジェクトのソースコード管理に含まない形にする。
(環境変数名は重複を考えるとリポジトリ名などを入れるのがよいか?)

# 設定例
export <リポジトリ名>_DB_PASSWORD=testpassword

ymlファイルの方も値を環境変数へ置き換える

# config.yml例
environment: develop

sqldriver: mysql
user: testuser
password: ${<リポジトリ名>_DB_PASSWORD}
protocol: tcp
address: 127.0.0.1:3306
database: TestDatabase

あとがき

データベース接続を行おうとした際にパスワードが必要になり、その流れで設定ファイルの取得方法を行なった。プロジェクトを適切に管理し、ソースコードを外部公開する場合などでは必須な対応のため、基本的な知識として学ぶ良い機会だった。


この記事が気に入ったらサポートをしてみませんか?