英文:
golang: how to support cli params, env vars and config file with viper but no cobra?
问题
我正在尝试编写一个只有一个命令的应用程序,因此,我在考虑是否可以跳过使用Cobra。
该应用程序应该能够支持所有类型的配置:
- 命令行参数
- 环境变量
- 配置文件
我正在使用viper,但无法读取我的命令行参数。
v := viper.New()
viper.SetConfigName("config")
viper.AddConfigPath(".")
v.SetDefault(pathKey, defaultPath)
fs := pflag.NewFlagSet("app", pflag.ExitOnError)
fs.String(pathKey, defaultPath, "Default path")
fs.StringSlice(wordsKey, []string{""}, "Words")
fs.String(loglevelKey, "info", "Log level")
if err := v.BindPFlags(fs); err != nil {
fmt.Println(err)
os.Exit(1)
}
if err := fs.Parse(os.Args[1:]); err != nil {
fmt.Println(err)
os.Exit(1)
}
v.AutomaticEnv()
if err := v.ReadInConfig(); err != nil {
fmt.Println("no conf file") //忽略,可以是命令行参数或配置文件
}
var c conf
if err := v.Unmarshal(&c); err != nil {
fmt.Println(err)
os.Exit(1)
}
但是我从未将命令行参数传递给conf结构体。在Unmarshal
之前打印v
不显示我提供的任何命令行参数。
我漏掉了什么?我需要使用Cobra吗?
还是我需要手动将每个flagset标志(例如fs.String(pathKey, defaultPath, "Default path")
)分配给配置结构体?
英文:
I am trying to write an app which only has one command, hence, I was thinking I might skip Cobra.
The app should be able to support all types of config:
- command line params
- env vars
- config file
I am using viper but I can't get it to read my cli params.
v := viper.New()
viper.SetConfigName("config")
viper.AddConfigPath(".")
v.SetDefault(pathKey, defaultPath)
fs := pflag.NewFlagSet("app", pflag.ExitOnError)
fs.String(pathKey, defaultPath, "Default path")
fs.StringSlice(wordsKey, []string{""}, "Words")
fs.String(loglevelKey, "info", "Log level")
if err := v.BindPFlags(fs); err != nil {
fmt.Println(err)
os.Exit(1)
}
if err := fs.Parse(os.Args[1:]); err != nil {
fmt.Println(err)
os.Exit(1)
}
v.AutomaticEnv()
if err := v.ReadInConfig(); err != nil {
fmt.Println("no conf file") //ignore, it can be either cli params, or conf file
}
var c conf
if err := v.Unmarshal(&c); err != nil {
fmt.Println(err)
os.Exit(1)
}
But I never get the cli params into the conf struct. Printing v
before the Unmarshal
doesn't show any of the cli params I provide.
What am I missing? Do I need to use cobra for this?
Or do I have to assign each flagset flag, e.g. fs.String(pathKey, defaultPath, "Default path")
, manually to the config struct?
答案1
得分: 1
为了后世,我认为我找到了问题所在:
我的conf
结构体的键名与标志不对应。例如,设置json:"logLevel"
,而字段名为DisplayLogLevel
是不够的,必须是:
const (
pathKey = "path"
wordsKey = "words"
logLevelKey = "logLevel"
)
type conf struct {
Path string `json:"path"`
Words []string `json:"words"`
LogLevel string `json:"logLevel"`
}
英文:
For posterity, I think I found the issue:
My conf
struct didn't have the correspondent key names as the flags do. Setting the json:"logLevel"
for example while the field is called DisplayLogLevel is not enough, it must be:
const (
pathKey = "path"
wordsKey = "words"
logLevelKey = "logLevel"
)
type conf struct {
Path string `json:"path"`
Words []string `json:"words"`
LogLevel string `json:"logLevel"`
}
答案2
得分: 0
也许你需要设置配置类型。从https://github.com/spf13/viper中获取:
viper.SetConfigType("yaml") // 如果配置文件的名称中没有扩展名,则需要设置此项
英文:
maybe you have to set config type. From https://github.com/spf13/viper:
viper.SetConfigType("yaml") // REQUIRED if the config file does not have the extension in the name
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论