Golangでyamlの構造化データをシングルトン化する
本章では、Go言語でYamlファイルを読み込み、構造化したデータをシングルトンとして利用する方法について共有します
背景
本番環境とローカル環境で、プロジェクト独自の設定を分離して記述して使い分ける必要がありました。そこで、yamlなどの設定ファイルを用意し、「flag」を用いて実行時の引数で設定ファイルの読み替えを行うことで、実現することとしました。そして合わせて、yamlの構造データをシングルトン化して、どこからでも呼び出せるようにします。
準備
プロジェクトにyamlファイルを用意します。
[hogehoge.yaml]
db: network: tcp host: 127.0.0.1 port: 3306 user: root password: foo name: HogeHoge
今回は、DBの設定をyamlファイルにサンプルとして用意しました。
次に、yamlファイルを読み込み、シングルトン化する処理を用意します。yamlファイルの読み込みには、以下のGo公式のライブラリを利用します。
godoc.org
なお実現にあたって、ライブラリ公式の名前をエイリアス「yml」として利用しています。
import ( "fmt" yml "gopkg.in/yaml.v2" "io/ioutil" "log" "sync" ) type yaml struct { Db db `yaml:"db"` } type db struct { Network string `yaml:"network"` Host string `yaml:"host"` Port string `yaml:"port"` User string `yaml:"user"` Password string `yaml:"password"` Name string `yaml:"name"` } // プロジェクト設定を呼び出す func Yaml() *yaml { // 一度だけ実行される onceYaml.Do(func() { initializeYaml() }) return instanceYaml } var instanceYaml *yaml var onceYaml sync.Once // yamlファイルから構造体を生成 func initializeYaml() { fmt.Println("*** YAML *** start loading yaml file") // yamlファイルを読み込む // ※ フラグから読み込みファイルを切り替えるほうがベター buf, err := ioutil.ReadFile("hogehoge.yaml") if err != nil { log.Fatalln(err) } // シングルトン化 // ※ ここで一度だけyamlの構造体をインスタンス化されます instanceYaml = &yaml{} err = yml.Unmarshal(buf, instanceYaml) if err != nil { log.Fatalln(err) } fmt.Println("*** YAML *** finished loading yaml file") }
運用
以下のように利用します。
con := sql.Open( "mysql", fmt.Sprintf( "%s:%s@%s(%s:%s)/%s?parseTime=true&loc=Asia%%2FTokyo", Yaml().Db.User, Yaml().Db.Password, Yaml().Db.Network, Yaml().Db.Host, Yaml().Db.Port, Yaml().Db.Name, ), )
実行するとコンソール上のログに、一度だけのみファイルが読み込まれていると表示されます。