【Go初学】設定ファイル、環境変数から設定情報を取得する
概要
プロジェクトを構成する定数をアプリ内に埋め込まず、環境によって切り替えられるよう外部ファイルとして設定しておきたい。さらにその中でもパスワードなど外部非公開にしたい秘匿情報は、より公開リスクを少なくするため環境変数へ設定し、設定情報を取得する。
設定ファイル情報の取得
データを簡易に扱いやすいymlファイルを設定ファイルとする。設定ファイルも間違いが起こりにくいよう書きやすさや読みやすさが大事。他にJSONやiniファイルもあるが、書き方がちょっと面倒だったり、Windows系ファイルのようだったりする。
▼ymlファイルの作成
プロジェクトのsrc下などに配置。配列やネスト構造でなければ単にコロン区切りで「キー名:値」とするだけでよい。
# config.yml例
environment: 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
あとがき
データベース接続を行おうとした際にパスワードが必要になり、その流れで設定ファイルの取得方法を行なった。プロジェクトを適切に管理し、ソースコードを外部公開する場合などでは必須な対応のため、基本的な知識として学ぶ良い機会だった。