南蛮千治の再発明じゃがすくなくともわたしは毎回ググるのでメモ
ちなみに
アプリやプログラムの設定におけるこのような変数に関しては、オライリーの実用 Go言語によれば
プログラムの挙動を変更する手段として、近年見直されているのが環境変数です。<中略>クラウド時代になって環境変数が強く推奨されるようになりました。<中略>特に実行ログに残ってほしくない、外部サーバーへのアクセスに用いる認証情報などは環境変数を利用してアプリケーションに渡すことが多いでしょう。
(引用: 1.7.2 環境変数)
と書かれており、けっこう前から設定ファイルなんてのはもう古臭い感じがあるらしい。知らんかった...まあdockerとかAWSとかとは無縁なのでgithubで設定ファイルおもらしなんてのがありえないっていうそういう感じでおりますので...(そもそも今の社はIT企業ですら無いのでgithubなんぞ使ってないので...)
いいわけはこのへんにしといてさっさと実装いきます
ディレクトリ
以下のような感じ。おわかりのとおり「ちょっと試してみるか」用のサブディレクトリsandbox
下に書いたので記事内のプログラムにハードコーディングで出てくるディレクトリ階層は実際につかうときはこんなんじゃないけど、めんどくさいのでそのまま載せることにしてます。意識低い
$ tree <application name(project root)> ├── go.mod ├── go.sum ├── sandbox │ ├── config │ │ └── config.go │ ├── config.ini │ └── main.go . .. ...(ほんとはこの先にアプリとかある)
sandbox/config/config.go
からsandbox/config.ini
を読み出したりします。
実装
設定ファイルはこんな感じにしてみました。データベースとか認証情報とかあるけど今回は実際に使うわけじゃないです。ただの例です
[app] client_id = <id> client_secret = <secret value> access_token = <access token> [web] port = 6666 [db] driver = sqlite3
で、キモとなるのがこちらのconfig.go
package config import ( "log" "gopkg.in/ini.v1" ) type ConfigList struct { App WebCfg DbCfg } type App struct { ClientId string ClientSecret string AccessToken string } type WebCfg struct { Port string } type DbCfg struct { SQLDriver string } var Cfg ConfigList func init() { LoadConfig() } func LoadConfig() { cfg, err := ini.Load("sandbox/config.ini") if err != nil { log.Fatalln(err) } Cfg = ConfigList{ App: App{ ClientId: cfg.Section("app").Key("client_id").String(), ClientSecret: cfg.Section("app").Key("client_secret").String(), AccessToken: cfg.Section("app").Key("access_token").String(), }, WebCfg: WebCfg{ Port: cfg.Section("web").Key("port").String(), }, DbCfg: DbCfg{ SQLDriver: cfg.Section("db").Key("driver").String(), }, } } func GetConfig(sectionName, key string) (string, error) { cfg, err := ini.Load("config.ini") if err != nil { return "", err } return cfg.Section(sectionName).Key(key).String(), nil } func UpdateConfig(sectionName, key, value string) error { cfg, err := ini.Load("sandbox/config.ini") if err != nil { return err } cfg.Section(sectionName).Key(key).SetValue(value) cfg.SaveTo("sandbox/config.ini") LoadConfig() return nil }
ようはgopkg.in/ini.v1
のマニュアル読みましょうねということなんだけど、まあハンズオンとしてね....
こちらがmain.go
。とくになんもしてない。
package main import ( "<application name>/sandbox/config" "fmt" ) func main() { fmt.Println("config.iniを設定ファイルとして読み書きするテスト") fmt.Println(config.Cfg.App) fmt.Println(config.Cfg.App.AccessToken) fmt.Println(config.Cfg.WebCfg) fmt.Println(config.Cfg.DbCfg) fmt.Println(config.Cfg.DbCfg.SQLDriver) config.UpdateConfig("web", "port", "8888") fmt.Println(config.Cfg.WebCfg.Port) }
ファイルの更新は、正直そうとう雑なのでもっとちゃんとしたやり方があるはずなんだけどよくわかんないので直接渡してるだけ。ここはなんの参考にもならなさそう。あれ?結局環境変数使ったほうが楽そうじゃない??