网站建设维护学习,seo是什么及作用,2024小学生时事新闻十条,小程序快速搭建平台本篇文章是 Go 标准库 flag 包的快速上手篇。
概述
开发一个命令行工具#xff0c;视复杂程度#xff0c;一般要选择一个合适的命令行解析库#xff0c;简单的需求用 Go 标准库 flag 就够了#xff0c;flag 的使用非常简单。
当然#xff0c;除了标准库 flag 外#x…
本篇文章是 Go 标准库 flag 包的快速上手篇。
概述
开发一个命令行工具视复杂程度一般要选择一个合适的命令行解析库简单的需求用 Go 标准库 flag 就够了flag 的使用非常简单。
当然除了标准库 flag 外也有不少的第三方库。比如为了替代 flag 而生的 pflag它支持 POSIX 风格的命令行解析。关于 POSIX 风格本文末尾有个简单的介绍。
更多与命令行处理相关的库可以打开 awesome-go#command-line 命令行一节查看star 最多的是 spf13/cobra 和 urfave/cli 与 flag / pflag 相比它们更加复杂是一个完全的全功能的框架。
有兴趣都可以了解下。
目标案例
回归主题继续介绍 flag 吧。通过案例介绍包的使用会比较直观。
举一个例子说明吧。假设现在要开发一个 Go 语言环境的版本管理工具gvggo version management by go。
命令行的帮助信息如下
NAME:gvg - go version management by goUSAGE:gvg [global options] command [command options] [arguments...]VERSION:0.0.1COMMANDS:list list go versionsinstall install a go versioninfo show go version infouse select a versionuninstall uninstall a go versionget get the latest codeuninstall uninstall a go versionhelp, h Shows a list of commands or help for one commandGLOBAL OPTIONS:--help, -h show help--version, -v print the version这个命令不仅包含了全局的选项还有 8 个子命令部分子命令支持参数和选项。暂时子命令的选项参数先不列出来了实现时再看。
接下来我们试着通过 flag 实现这个效果。本文只介绍 GLOBAL OPTIONS全局选项的实现。 如果想了解什么是 Go 语言环境的版本管理可以查看 如何灵活地进行 Go 版本管理 一文。 选项表示
最简单的命令不需要任何参数和选项复杂一点要支持参数和选项的配置。gvg 没有全局参数或者说全局参数是子命令全局选项有 --help -h 和 --version -h。
一个选项在 flag 包中用一个 Flag 表示那 -h 可以用一个 Flag 表示。一个选项通常由几个部分组成如名称、使用说明和默认值。如果将 -h 用代码表示如下
h : flag.Bool(h, false, show help)定义了一个布尔类型的 Flag名为 h默认值是 false使用说明为 “show help”。变量 h 是一个布尔型的指针通过它可以取出命令行传入的值。
除了使用 flag.Bool还可以使用另外一种方式Flag.BoolVar 定义一个 Flag。我们可以用这种方式定义 -v 选项。
代码如下
var v bool
flag.BoolVar(v, v, false, print the version)最后的三个参数含义与 flag.Bool 相同主要区别在值的获取方式flag.BoolVar 是通过将变量地址传入获取值。从经验来看第二种方式使用的较多或许因为第一种方式会发生变量逃逸。
更多类型
除了布尔类型Flag 的类型还有整数int、int64、uint、uint64、浮点数float64、字符串string和时长time.Duration。
假设 gvg 的案例中支持配置文件选项 --config-path。实现代码如下
var configPathflag.StringVar(configPath, config-path, , config file path)通过 StringVar 定义了新的 Flag。使用方式与 BoolVar 相同最后的三个参数分别是选项名称、默认值和使用说明。
虽然 flag 支持的内置类型并不多但已经满足大部分需求了。如果有自定义的需求也可以扩展新的类型实现这部分内容下篇介绍。
长短选项
现在已经完成了 -h 和 -v 两个选项但目标是 -v --version 和 -h --help即同时支持长短选项。
一个 Flag 应该有长短两种形式但 flag 包并不支持这种风格需要曲线救国才能实现。注本文开开头提到的 pflag 支持。
这里以 -v --version 为例代码如下
flag.BoolVar(v, v, false, print the version)
flag.BoolVar(v, version, false, print the version)定义了两个 Flag同时绑定到了一个变量上。这种效果只能用 flag.BoolVar 方式定义新的 Flagflag.Bool 没办法做到将同一个变量同时绑定两个 Flag。
但其实这种也有缺点先不说了后面介绍帮助信息打印时就明白了。
命令行解析
定义好所有 Flag还需要一步解析才能拿到正确的结果。这一步非常简单调用 flag.Parse() 即可。
如下是完整的代码
package mainvar h *bool
var v boolfunc init() {flag.BoolVar(h, h, false, show help)flag.BoolVar(h, help, false, show help)flag.BoolVar(v, v, false, print the version)flag.BoolVar(v, version, false, print the version)
}func main() {flag.Parse()fmt.Println(version, v)fmt.Println(help, h)
}通过 flag.Parse() 解析完成打印下 v 和 h 变量确认下是否成功获取到了值。
到此代码就告一段落了现在将它编译为 gvg 命令吧。
使用命令
在正式使用命令前先介绍下 flag 的语法。官方文档说明命令行中 flag 选项的使用语法有如下几种形式。
-flag
-flagx
-flag x // 非布尔类型才支持这种方式但其实-- 也是支持的。因此上面才可以实现 --version 的曲线救国。
使用下这个命令将 help 设置为 false 和 version 设置为 true。我尽量把所有可能的写法都列出来。
$ gvg -v
$ gvg -version -hfalse # 单个 - 即 -version 支持
$ gvg --versiontrue --helpfalse
$ gvg --version1 --help0
$ gvg --versiont --helpf
$ gvg --versionT --helpF
$ gvg --version true --help true # 写法错误因为无法识别出是 bool 值还是参数或子命令
$ gvg -vh # 不支持这种风格执行命令输出结果
version true
help false到这里flag 的快速入门就介绍完了。参数留在子命令的时候介绍。
命令行风格
由于一些历史原因Unix 出现过很多不同的分支命令行的风格也因此有很多标准比如
Unix 风格选项采用单 - 加一个字母比如 -v短选项就是它优点是足够简洁;BSD 风格选项没有 -没有任何的前缀不知道有参数的情况怎么处理没有研究;GNU 风格采用 --如 --version长选项扩展性好但是要多打几个字母;
在网上找到一个搞笑漫画。 查看系统进程有两种写法 ps auxBSD 风格 和 ps -elfUnix 风格。之前我一直很郁闷为什么有这个区别。现在算是明白了。哈哈。
POSIX 的命令行风格算是取长补短的集合吧。什么是 POSIX 风格可以查看这篇文档 命令参数语法。它同时提供了长短选项的标准。
要明白的是标准终究只是标准很多命令其实并不遵循它。但自己在设计命令行规范的时候最好还是要有一套标准而参考最统一的标准肯定是没错的。
总结
本文介绍了 Go 中 flag 包的使用一般的场景已经足够使用了。
博文地址Go 命令行解析 flag 包之快速上手