我使用json檔案來配置我的程式引數并使用flag包來配置相同的引數。
當json檔案同時決議某些引數flag時,我希望使用通過flag.
麻煩的是json檔案路徑也是通過flag. 呼叫后可以得到json路徑flag.parse(),但是引數也會被決議,那么Unmarshaljson會覆寫flag決議的引數。
示例 json:
{
"opt1": 1,
"opt2": "hello"
}
示例代碼:
var Config = struct {
Opt1 int `json:"opt1"`
Opt2 string `json:"opt2"`
}{
Opt1: 0,
Opt2: "none",
}
func main() {
// parse config file path
var configFile string
flag.StringVar(&configFile, "config", "", "config file path")
// parse options
flag.IntVar(&Config.Opt1, "opt1", Config.Opt1, "")
flag.StringVar(&Config.Opt2, "opt2", Config.Opt2, "")
// parse flags
flag.Parse()
// load config options from config.json file
if configFile != "" {
if data, err := ioutil.ReadFile(configFile); err != nil {
fmt.Printf("read config file error: %v\n", err)
} else if err = json.Unmarshal(data, &Config); err != nil {
fmt.Printf("parse config file error: %v\n", err)
}
}
fmt.Printf("% v", Config)
}
程式示例輸出:
./foo.exe -opt2 world
out:{Opt1:0 Opt2:world}
./foo.exe -config config.json
出去:{Opt1:1 Opt2:hello}
./foo.exe -config config.json -opt2 world
真正出局:{Opt1:1 Opt2:hello}
希望出局:{Opt1:1 Opt2:world}
uj5u.com熱心網友回復:
一個簡單的解決方案是首先決議 JSON 組態檔,一旦完成,然后繼續決議 CLI 引數。
問題在于 JSON 組態檔也是 CLI arg。
flag.Parse()最簡單的解決方案是在決議組態檔后再次呼叫:
// load config options from config.json file
if configFile != "" {
if data, err := ioutil.ReadFile(configFile); err != nil {
fmt.Printf("read config file error: %v\n", err)
} else if err = json.Unmarshal(data, &Config); err != nil {
fmt.Printf("parse config file error: %v\n", err)
}
// parse flags again to have precedence
flag.Parse()
}
第二個flag.Parse()將覆寫,因此優先于來自 JSON 檔案的資料。
有了這個添加,運行
./foo.exe -config config.json -opt2 world
輸出將是您想要的:
{Opt1:1 Opt2:world}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/480228.html
