Go 应用构建:pflag、viper、cobra

date
May 19, 2023
slug
pflag&viper&cobra
status
Published
tags
Code
Go
summary
pflag、viper、cobra 的使用场景和使用方式
type
Post
Created Time
Oct 28, 2023 01:45 PM
Updated Time
Oct 28, 2023 01:45 PM
AI summary
介绍了 Go 语言中使用 pflag、viper、cobra 库进行应用构建的方法。其中,pflag 用于处理命令行参数,viper 用于处理配置文件,cobra 用于构建命令行工具。详细介绍了这些库的使用方法,包括读取配置、添加命令、添加嵌套子命令、添加非选项参数验证、添加钩子函数等。
Status
很多 Go 应用在构建过程中,都会使用 pflagvipercobra 这三个仓库,今天,我想记录一下对这三个库的理解、使用场景和使用方式。
在介绍这三个库之前,首先说一下这三个库的作者—— Steve Francia,他在个人主页是这样介绍自己的:“我的名字是史蒂夫-弗朗西亚。27 年的时间里,我是一名软件开发者,是一名产品经理,同时也是一个宣传领导者,在开源社区的这些年里,期冀能够有效“提升”开发者的用户体验。”如果你还不了解他,强烈建议去他的 GitHub 主页看一眼,一定会印象深刻。Steve Francia 在 2016 年加入 Google,2022 年离开谷歌,在加入 Google 时,他就公开表示,自己会在 6 年后离开 Google。在 Google 的 6 年时间里,他领导的 Go 团队,大大改善了 Go 的开发体验,为 Go 语言的蓬勃发展做出了巨大的贡献。

pflag

一个命令行解析工具。与 flag 包的工作原理甚至是代码实现都是类似的,在一些地方做了优化:
  • 支持的参数类型更多,如增加了 IP、IP Mask、IP Net、Count、各种类型的 Slice 类型等。
  • 支持更丰富的功能,如 shorthand、deprecated、hidden 等高级功能。
除此之外,pflag 还兼容了 flag 库的 Flag 和 FlagSet,有点儿像是对 flag 的扩展,让你可以更方便的解析命令行。

使用

pflag 的使用非常简单,如下:
其结果可能有三种:
  1. 什么都不做,则 ip 最终为 1234;
  1. 设置了 —flagname 但是没有设置值,则 ip 最终为 4321;
  1. 设置 —flagname=9999,则 ip 最终为 9999;
更多使用方式,查阅官方文档

viper

一个配置管理工具。主要有三大特性:
  • 支持多种格式的配置文件;
  • 支持多种方式读入配置;
  • 支持多种方式读取配置;

多种格式

阅读 viper 的源码可以看到,viper 支持如下几种格式的配置文件:
  • YAML
  • JSON
  • HCL
  • Java Properties
  • TOML
  • ENV
  • Initialization File

多种方式读入配置

viper 可以从不同的位置读取配置,不同位置的配置具有不同的优先级,高优先级的配置会覆盖低优先级相同的配置,按优先级从高到低排列如下:通过 viper.Set 函数显示设置的配置→命令行参数→环境变量→Key/Value 存储→默认值。需要注意,viper 配置键不区分大小写。

通过 viper.Set 函数显示设置的配置

命令行参数

环境变量

Key/Value 存储(通过配置文件进行设置)

默认值

多种方式读取配置

Get(key string) interface{}

假设 JSON 文件中的值如下:
访问 JSON 文件中的值:

Get<Type>(key string) <Type>

其中,<Type> 是 viper 支持的类型,首字母大写:Bool、Float64、Int、IntSlice、String、StringMap、StringMapString、StringSlice、Time、Duration,如 GetInt()。

AllSettings() map[string]interface{}

用于将配置序列化成字符串,如将 Viper 中保存的所有设置序列化到一个字符串中:

IsSet(key string) : bool

检查给定的键是否存在。

反序列化

提供了两种方法
  • Unmarshal(rawVal interface{}) error
  • UnmarshalKey(key string, rawVal interface{}) error
使用方式如下:
更多使用方式,参考官方文档

cobra

一个命令行工具。主要有以下特性:
  • 自定义命令,添加、修改,重定义等;
  • 智能提示和自动补全,比如,当我们输入的命令有误时,Cobra 会根据注册的命令,推算出可能的命令;
  • 嵌套子命令;
  • 提供了对应的脚手架,轻松生成程序框架;
cobra 的命令行结构由三部分组成:
  • 命令(Command):就是需要执行的操作;
  • 参数(Arg):命令的参数,即要操作的对象;
  • 选项(Flag):命令选项可以调整命令的行为。
cobra 认为,一个好的命令要如同一个句子一样符合语法以及直观。
许多知名的开源项目都使用了 cobra 库构建命令行,如 kubernetedocker/composehugoetcdistio 等。

下载

执行如下命令进行下载 cobra-cli 命令行工具
下载完成后执行 cobra-cli -h 进行验证。

初始化

cobra 的使用非常简单,需要使用如下命令进行初始化:
初始化完毕后,项目会自动生成如下结构:
这个结构符合 cobra 的标准结构规范。

添加命令

就会在 cmd 文件夹下生成一个 version.go 文件,我们可以根据需要,修改 root.go 文件中的内容。

添加嵌套子命令

嵌套子命令需要先添加命令,如通过 cobra-cli add test 命令增加 test.go 文件,再修改 test.go 文件中的 init 函数:
测试嵌套子命令:

添加非选项参数验证

在命令的过程中,经常会传入非选项参数,并且需要对这些非选项参数进行验证,cobra 提供了机制来对非选项参数进行验证。可以使用 command 的 args 字段来验证非选项参数。cobra 也内置了一些验证函数:
  • NoArgs:如果存在任何非选项参数,该命令将报错。
  • ArbitraryArgs:该命令将接受任何非选项参数。
  • OnlyValidArgs:如果有任何非选项参数不在 Command 的 ValidArgs 字段中,该命令将报错。
  • MinimumNArgs(int):如果没有至少 N 个非选项参数,该命令将报错。
  • MaximumNArgs(int):如果有多于 N 个非选项参数,该命令将报错。
  • ExactArgs(int):如果非选项参数个数不为 N,该命令将报错。
  • ExactValidArgs(int):如果非选项参数的个数不为 N,或者非选项参数不在 Command 的 ValidArgs 字段中,该命令将报错。
  • RangeArgs(min, max):如果非选项参数的个数不在 min 和 max 之间,该命令将报错。
使用预定义验证函数,示例如下:
自定义验证函数,示例如下:

添加钩子函数

在运行 Run 函数时,我们可以运行一些钩子函数,在 Run 函数之前执行(或执行之后)执行。这些函数的执行顺序如下:
  1. PersistentPreRun;
  1. PreRun
  1. Run
  1. PostRun
  1. PersistentPostRun
其中,父级的 PreRun 只会在父级命令运行时调用,子命令是不会调用。
示例如下:
输出:
更多使用方式,查看官方文档
 

© 孙东辉 2022 - 2025