英文:
Config file with cobra and viper
问题
基本信息: 我创建了一个 Go 应用程序,并使用了 Cobra。Cobra 使用 Viper 来处理命令行参数和标志。
我有一个名为 listen 的命令,其中有一个名为 bind 的标志,我想在一个 YAML 文件中对其进行配置。
代码:
listen 命令的 init 函数如下所示:
func init() {
RootCmd.AddCommand(listenCmd)
listenCmd.Flags().StringP("bind", "b", ":50051", "Provide bind definition")
viper.BindPFlag("bind", listenCmd.Flags().Lookup("bind"))
}
我的应用程序代码位于 https://github.com/sascha-andres/go-logsink
问题:
当我使用 listen --bind "bla"
调用应用程序时,标志被正确设置为 bla
,但我尚未找到一种方法来使用位于我的主目录中的 YAML 文件实现这一点。
尝试的配置文件:
---
connect:
bind: "bla"
和
---
bind: "bla"
在这两种情况下,配置文件都被找到了,但标志的值不是预期的值,而是默认值。
我应该如何编写配置文件才能正确填充标志的值?
英文:
Basic information: I have created a go application and used Cobra for it. Cobra uses Viper for command line parameters and flags.
I have a command listen with a flag bind and I want to configure it in a yaml file.
Code:
The init function of the listen command looks like this:
func init() {
RootCmd.AddCommand(listenCmd)
listenCmd.Flags().StringP("bind", "b", ":50051", "Provide bind definition")
viper.BindPFlag("bind", listenCmd.Flags().Lookup("bind"))
}
Code of my application is at https://github.com/sascha-andres/go-logsink
Problem:
When I call the app with listen --bind "bla"
the flag is set correctly to bla
, but I have not found a way to achieve this using a YAML file located in my home directory.
Config files tried:
---
connect:
bind: "bla"
and
---
bind: "bla"
In both cases the config file was found but the flag had not the expected value but the default value.
How do I have to write the config file to have the flag populated correctly?
答案1
得分: 9
好的,以下是翻译好的内容:
好的,感谢您提供的额外信息,这对我很有帮助!
问题
问题出在您获取标志值的方式上。以下是您目前的代码:
bind := cmd.Flag("bind").Value.String()
fmt.Printf("Binding definition provided: %s\n", bind)
server.Listen(bind)
当使用 viper 绑定标志时,实际上是 viper 会保存最终的值,按照以下优先级:
1. 如果存在,使用标志值
2. 否则,使用配置文件中的值
3. 否则,使用默认的标志值
您的问题在于您从命令的标志集中获取标志值,而不是从 viper 中获取。
行为
以下是我测试的代码:
bind := cmd.Flag("bind").Value.String()
fmt.Printf("Binding definition provided: %s\n", bind)
fmt.Printf("Binding definition provided from viper: %s\n", viper.GetString("bind"))
没有设置 bind 配置参数时:
$ go-logsink listen
Using config file: /xxx/.go-logsink.yaml
Binding definition provided: :50051
Binding definition provided from viper: :50051
将 bind 配置参数设置为 "bla"(非嵌套,第二个配置文件)时:
$ go-logsink listen
Using config file: /xxx/.go-logsink.yaml
Binding definition provided: :50051
Binding definition provided from viper: bla
将 bind 配置参数设置为 "bla"(非嵌套,第二个配置文件)并使用显式标志时:
$ go-logsink listen --bind ":3333"
Using config file: /xxx/.go-logsink.yaml
Binding definition provided: :3333
Binding definition provided from viper: :3333
底线:当使用 viper 绑定标志时,请使用 viper 来获取它们。
附加说明:在您的 README 中,生成与 grpc 兼容的代码的正确方式是将 grpc 插件添加到 protobuf 生成中:protoc --go_out=plugins=grpc:. *.proto
英文:
Ok, thanks for the additional information, It helped a lot !
Problem
The problem arises from the way you're retrieving the value of the flag. Here is what you currently have:
bind := cmd.Flag("bind").Value.String()
fmt.Printf("Binding definition provided: %s\n", bind)
server.Listen(bind)
When binding a flag with viper, it's actually viper that will hold the final value, according to this priorities:
1. If present, use the flag value
2. Else, use the value from the config file
3. Else, use the default flag value
Your problem is that you retrieve the flag value from the flag set of the command, and not from viper.
Behavior
Here is the code I tested:
bind := cmd.Flag("bind").Value.String()
fmt.Printf("Binding definition provided: %s\n", bind)
fmt.Printf("Binding definition provided from viper: %s\n", viper.GetString("bind"))
Without the bind config param:
$ go-logsink listen
Using config file: /xxx/.go-logsink.yaml
Binding definition provided: :50051
Binding definition provided from viper: :50051
With the bind config param set to "bla" (not nested, second config file):
$ go-logsink listen
Using config file: /xxx/.go-logsink.yaml
Binding definition provided: :50051
Binding definition provided from viper: bla
With the bind config param set to "bla" (not nested, second config file) and an explicit flag:
$ go-logsink listen --bind ":3333"
Using config file: /xxx/.go-logsink.yaml
Binding definition provided: :3333
Binding definition provided from viper: :3333
Bottomline : when binding your flags with viper, use viper to retrieve them.
Additional note : In your README, the proper way to generate grpc compatible code is by adding the grpc plugin to protobuf generation: protoc --go_out=plugins=grpc:. *.proto
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论