当前位置: 首页 > news >正文

Go 命令行解析 flag 包之快速上手

请添加图片描述

本篇文章是 Go 标准库 flag 包的快速上手篇。

概述

开发一个命令行工具,视复杂程度,一般要选择一个合适的命令行解析库,简单的需求用 Go 标准库 flag 就够了,flag 的使用非常简单。

当然,除了标准库 flag 外,也有不少的第三方库。比如,为了替代 flag 而生的 pflag,它支持 POSIX 风格的命令行解析。关于 POSIX 风格,本文末尾有个简单的介绍。

更多与命令行处理相关的库,可以打开 awesome-go#command-line 命令行一节查看,star 最多的是 spf13/cobra 和 urfave/cli ,与 flag / pflag 相比,它们更加复杂,是一个完全的全功能的框架。

有兴趣都可以了解下。

目标案例

回归主题,继续介绍 flag 吧。通过案例介绍包的使用会比较直观。

举一个例子说明吧。假设,现在要开发一个 Go 语言环境的版本管理工具,gvg(go 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() 解析完成,打印下 vh 变量,确认下是否成功获取到了值。

到此,代码就告一段落了,现在将它编译为 gvg 命令吧。

使用命令

在正式使用命令前,先介绍下 flag 的语法。官方文档说明,命令行中 flag 选项的使用语法有如下几种形式。

-flag
-flag=x
-flag x // 非布尔类型才支持这种方式

但其实,-- 也是支持的。因此,上面才可以实现 --version 的曲线救国。

使用下这个命令,将 help 设置为 falseversion 设置为 true。我尽量把所有可能的写法都列出来。

$ gvg -v
$ gvg -version -h=false  # 单个 - ,即 -version 支持
$ gvg --version=true --help=false
$ gvg --version=1 --help=0
$ gvg --version=t --help=f
$ gvg --version=T --help=F
$ gvg --version true --help true # 写法错误,因为无法识别出是 bool 值,还是参数或子命令
$ gvg -vh  # 不支持这种风格

执行命令,输出结果:

version true
help false

到这里,flag 的快速入门就介绍完了。参数留在子命令的时候介绍。

命令行风格

由于一些历史原因,Unix 出现过很多不同的分支,命令行的风格也因此有很多标准,比如:

  • Unix 风格,选项采用单 - 加一个字母,比如 -v,短选项就是它,优点是足够简洁;
  • BSD 风格,选项没有 -,没有任何的前缀,不知道有参数的情况怎么处理,没有研究;
  • GNU 风格,采用 --,如 --version,长选项,扩展性好,但是要多打几个字母;

在网上找到一个搞笑漫画。

请添加图片描述

查看系统进程有两种写法, ps aux(BSD 风格) 和 ps -elf(Unix 风格)。之前,我一直很郁闷为什么有这个区别。现在算是明白了。哈哈。

POSIX 的命令行风格算是取长补短的集合吧。什么是 POSIX 风格?可以查看这篇文档 命令参数语法。它同时提供了长短选项的标准。

要明白的是,标准终究只是标准,很多命令其实并不遵循它。但自己在设计命令行规范的时候,最好还是要有一套标准,而参考最统一的标准肯定是没错的。

总结

本文介绍了 Go 中 flag 包的使用,一般的场景已经足够使用了。

博文地址:Go 命令行解析 flag 包之快速上手

相关文章:

Go 命令行解析 flag 包之快速上手

本篇文章是 Go 标准库 flag 包的快速上手篇。 概述 开发一个命令行工具,视复杂程度,一般要选择一个合适的命令行解析库,简单的需求用 Go 标准库 flag 就够了,flag 的使用非常简单。 当然,除了标准库 flag 外&#x…...

React16源码: React中commitAllHostEffects内部的commitDeletion的源码实现

commitDeletion 1 )概述 在 react commit 阶段的 commitRoot 第二个while循环中调用了 commitAllHostEffects,这个函数不仅仅处理了新增节点,更新节点最后一个操作,就是删除节点,就需要调用 commitDeletion&#xff0…...

[机器学习]简单线性回归——梯度下降法

一.梯度下降法概念 2.代码实现 # 0. 引入依赖 import numpy as np import matplotlib.pyplot as plt# 1. 导入数据(data.csv) points np.genfromtxt(data.csv, delimiter,) points[0,0]# 提取points中的两列数据,分别作为x,y …...

2024年搭建幻兽帕鲁服务器价格多少?如何自建Palworld?

自建幻兽帕鲁服务器租用价格表,2024阿里云推出专属幻兽帕鲁Palworld游戏优惠服务器,配置分为4核16G和4核32G服务器,4核16G配置32.25元/1个月、3M带宽96.75元/1个月、8核32G配置10M带宽90.60元/1个月,8核32G配置3个月271.80元。ECS…...

『OpenCV-Python|鼠标作画笔』

Opencv-Python教程链接:https://opencv-python-tutorials.readthedocs.io/ 本文主要介绍OpenCV-Python如何将鼠标作画笔绘制圆或者矩形。 示例一:图片上双击的位置绘制一个圆圈 首先创建一个鼠标事件回调函数,鼠标事件发生时就会被执行。鼠标…...

关于如何利用ChatGPT提高编程效率的

自从去年ChatGPT3.5推出以后,这一年时间在编程过程中我也在慢慢熟悉人工智能的使用,目前来看即使是免费的ChatGPT3.5对于编程效率的提升也是有很大帮助的,虽然在使用过程中确实出现了一些问题,本文记录下我的一些心得体会和用法。…...

Excel VBA ——从MySQL数据库中导出一个报表-笔记

本文主要涉及: VBA中数据库连接参数改成从配置文件获取 VBA连接MySQL数据库 VBA读MySQL数据库 演示两种写入工作簿的代码实现系统环境: Windows 10 64bit Excel 365 64bit WAMP(3.2.2.2 64bit)集成的MariaDB版本为10.4.10&#…...

金融OCR领域实习日志(一)——OCR技术从0到1全面调研

一、OCR基础 任务要求: 工作原理 OCR(Optical Character Recognition,光学字符识别)是指电子设备(例如扫描仪或数码相)检查纸上打印的字符,经过检测暗、亮的模式肯定其形状,而后用…...

ELK日志解决方案

ELK日志解决方案 ELK套件日志系统应该是Elasticsearch使用最广泛的场景之一了,Elasticsearch支持海量数据的存储和查询,特别适合日志搜索场景。广泛使用的ELK套件(Elasticsearch、Logstash、Kibana)是日志系统最经典的案例,使用Logstash和Be…...

嵌入式学习-驱动

嵌入式的一些基本概念 CPU与MCU的区别 CPU(中央处理器,central processing unit) 指集成了运算器、控制器、寄存器、高速缓存等功能模块的芯片,负责执行计算机程序指令的处理器。MCU(单片微型计算机或单片机,microco…...

系统架构17 - 软件工程(5)

软件工程 软件测试测试原则测试方法静态测试动态测试黑盒测试白盒测试灰盒测试自动化测试 测试阶段单元测试集成测试系统测试性能测试验收测试其它测试AB测试Web测试链接测试表单测试 测试用例设计黑盒测试用例白盒测试用例 调试 系统维护遗留系统系统转换转换方式数据转换与迁…...

空气质量预测 | Python实现基于线性回归、Lasso回归、岭回归、决策树回归的空气质量预测模型

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 政府机构使用空气质量指数 (AQI) 向公众传达当前空气污染程度或预测空气污染程度。 随着 AQI 的上升,公共卫生风险也会增加。 不同国家有自己的空气质量指数,对应不同国家的空气质量标准。 对于空气质量预测,…...

MYSQL数据库基本操作-DQL-基本查询

一.概念 数据库管理系统一个重要功能就是数据查询。数据查询不应是简单返回数据库中存储的数据,还应该根据需要对数据进行筛选以及确定数据以什么样的格式显示。 MySQL提供了功能强大,灵活的语句来实现这些操作。 MySQL数据库使用select语句来查询数据…...

gdb 调试 - 在vscode图形化展示在远程的gdb debug过程

前言 本地机器的操作系统是windows,远程机器的操作系统是linux,开发在远程机器完成,本地只能通过ssh登录到远程。现在目的是要在本地进行图形化展示在远程的gdb debug过程。(注意这并不是gdb remote !!&am…...

Android 13.0 SystemUI下拉状态栏定制二 锁屏页面横竖屏时钟都居中功能实现二

1.前言 在13.0的系统rom定制化开发中,在关于systemui的锁屏页面功能定制中,由于在平板横屏锁屏功能中,时钟显示的很大,并且是在左旁边居中显示的, 由于需要和竖屏显示一样,所以就需要用到小时钟显示,然后同样需要居中,所以就来分析下相关的源码,来实现具体的功能 如图…...

docker 部署xxl-job

docker 部署xxl-job XXL-JOB github地址 https://github.com/xuxueli/xxl-job XXL-JOB 文档地址 https://www.xuxueli.com/xxl-job/ XXL-JOB是一个分布式任务调度平台,其核心设计目标是开发迅速、学习简单、轻量级、易扩展。现已开放源代码并接入多家公司线上产品…...

Kafka(九)跨集群数据镜像

目录 1 跨集群镜像的应用场景1.1 区域集群和中心集群1.2 高可用(HA)和灾备(DR)1.3 监管与合规1.4 云迁移1.5 聚合边缘集群的数据 2 多集群架构2.1 星型架构2.2 双活架构2.2 主备架构2.2.1 如何实现Kafka集群的故障转移2.2.1.1 故障转移包括的内容1. 灾难恢复计划2. 非计划内的故…...

第3讲 谈谈final、finally、 finalize有什么不同?

参考 三者区别 final final 是 java 关键字可修饰变量(类成员变量、类静态变量、局部变量和形参):表示不可修改当前变量的值(这里的值可以是地址,也可以是基本类型的值)#(注意:fi…...

MC3172 串口模块

MC3172 支持12个串口对应关系如下 串口模块初始化 第一个是uart0~11 inpin RX 脚 管脚号 outpin TX脚 管脚号 baud 波特率 read_ptr ,数据读取指针 void uart_init(u32 uart_num,u8 in_pin,u8 out_pin,u32 baud,u8* read_ptr) {INTDEV_SET_CLK_RST(uart_num,(INTDEV_RUN|…...

VUE3 加载自定义SVG文件

网上代码通篇一律,需要修改多处地方,特别是component下还要创建一个index.vue的组件,奇奇怪怪。 要在 Vue 项目中使用 svg-sprite-loader 来管理 SVG 图标,你需要执行以下几个步骤: npm install svg-sprite-loader -…...

基于算法竞赛的c++编程(28)结构体的进阶应用

结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...

web vue 项目 Docker化部署

Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage)&#xff1a…...

Appium+python自动化(十六)- ADB命令

简介 Android 调试桥(adb)是多种用途的工具,该工具可以帮助你你管理设备或模拟器 的状态。 adb ( Android Debug Bridge)是一个通用命令行工具,其允许您与模拟器实例或连接的 Android 设备进行通信。它可为各种设备操作提供便利,如安装和调试…...

Oracle查询表空间大小

1 查询数据库中所有的表空间以及表空间所占空间的大小 SELECTtablespace_name,sum( bytes ) / 1024 / 1024 FROMdba_data_files GROUP BYtablespace_name; 2 Oracle查询表空间大小及每个表所占空间的大小 SELECTtablespace_name,file_id,file_name,round( bytes / ( 1024 …...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat(I/O Statistics)是Linux系统下用于监视系统输入输出设备和CPU使…...

基于当前项目通过npm包形式暴露公共组件

1.package.sjon文件配置 其中xh-flowable就是暴露出去的npm包名 2.创建tpyes文件夹,并新增内容 3.创建package文件夹...

【JavaWeb】Docker项目部署

引言 之前学习了Linux操作系统的常见命令,在Linux上安装软件,以及如何在Linux上部署一个单体项目,大多数同学都会有相同的感受,那就是麻烦。 核心体现在三点: 命令太多了,记不住 软件安装包名字复杂&…...

2023赣州旅游投资集团

单选题 1.“不登高山,不知天之高也;不临深溪,不知地之厚也。”这句话说明_____。 A、人的意识具有创造性 B、人的认识是独立于实践之外的 C、实践在认识过程中具有决定作用 D、人的一切知识都是从直接经验中获得的 参考答案: C 本题解…...

Python Einops库:深度学习中的张量操作革命

Einops(爱因斯坦操作库)就像给张量操作戴上了一副"语义眼镜"——让你用人类能理解的方式告诉计算机如何操作多维数组。这个基于爱因斯坦求和约定的库,用类似自然语言的表达式替代了晦涩的API调用,彻底改变了深度学习工程…...

FFmpeg:Windows系统小白安装及其使用

一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...