配置文件使用Cobra和Viper

huangapple go评论77阅读模式
英文:

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

huangapple
  • 本文由 发表于 2017年1月11日 04:56:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/41578264.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定