关于golang标准库flag的全面讲解_golang_脚本之家


本站和网页 https://www.jb51.net/article/261816.htm 的作者无关,不对其内容负责。快照谨为网络故障时之索引,不代表被搜索网站的即时页面。


关于Golang标准库flag的全面讲解_Golang_脚本之家
脚本之家
服务器常用软件
手机版
关注微信
快捷导航
软件下载
android
MAC
驱动下载
字体下载
DLL
源码下载
PHP
ASP.NET
ASP
JSP
软件编程
C#
JAVA
C 语言
Delphi
Android
网络编程
JavaScript
在线工具
CSS格式化
JS格式化
Html转化为Js
数据库
MYSQL
MSSQL
oracle
DB2
MARIADB
CMS
PHPCMS
DEDECMS
帝国CMS
WordPress
常用工具
PHP开发工具
python
Photoshop
必备软件
网站首页
网页制作
脚本专栏
脚本下载
服务器
电子书籍
操作系统
网站运营
平面设计
其它
媒体动画
电脑基础
硬件教程
网络安全
vbs
DOS/BAT
hta
htc
perl
游戏相关
VBA
远程脚本
ColdFusion
ruby
autoit
seraphzone
PowerShell
linux shell
Lua
Golang
Erlang
您的位置:
首页
→ Golang标准库flag
关于Golang标准库flag的全面讲解
 更新时间:2022年09月06日 09:09:06   作者:程序员读书​​​​​​​  
这篇文章主要介绍了关于Golang标准库flag的全面讲解,这个库的代码量只有1000行左右,却提供了非常完善的命令行参数解析功能,更多相关内容需要的朋友可以参考一下
目录
命令行参数
使用详解
选项语法
flag是怎么解析参数的?
自定义数据类型
短选项
小结
前言:
今天来聊聊Go语言标准库中一个非常简单的库flag,这个库的代码量只有1000行左右,却提供了非常完善的命令行参数解析功能。
如果你有使用过类Unix(比如MacOS,Linux)等操作系统,相信你应该明白命令参数是什么,比如下面的两条命令:
$ mysql -u root -p 123456
$ ls -al
第一条命令是MySQL的客户端,其
-u root
-p 123456
就是命令行参数,第二条命令用于显示当前目录的文件及目录,该命令中
-al
就是命令行参数。
flag库的作用就是帮我们将命令后面的选项参数解析到对应的变量中。
要了解一个库,须从使用开始,下面我们通过一个简单的示例来快速了解flag库的使用,这个示例可以接收从命令行传递的用于连接数据库的参数,
代码如下:
package main
import (
"flag"
"fmt"
var (
host
string
dbName
port
int
user
password string
func main() {
flag.StringVar(&host, "host", "", "数据库地址")
flag.StringVar(&dbName, "db_name", "", "数据库名称")
flag.StringVar(&user, "user", "", "数据库用户")
flag.StringVar(&password, "password", "", "数据库密码")
flag.IntVar(&port, "port", 3306, "数据库端口")
flag.Parse()
fmt.Printf("数据库地址:%s\n", host)
fmt.Printf("数据库名称:%s\n", dbName)
fmt.Printf("数据库用户:%s\n", user)
fmt.Printf("数据库密码:%s\n", password)
fmt.Printf("数据库端口:%d\n", port)
在命令行窗口输入以下命令,开始运行程序
go run main.go -host=localhost -user=test -password=123456 -db_name=test -port=3306
运行结束,输出结果如下所示:
数据库地址:localhost
数据库名称:test
数据库用户:test
数据库密码:123456
数据库端口:3306
上面的示例就是一个解析命令行选项参数的模板,包括下面三个步骤:
定义好接收参数的变量。
调用flag.StringVar()等函数将命令行选项与变量绑定。
调用flag.Parse()函数,开始解析变量。
在上面程序中,我们用了StringVar函数绑定字符串类型的参数,用了IntVar函数绑定整数类型的参数,除了字符串和整型,flag支持boolean,Duration,float64,Int64,uint,uint64等类型,下面是这些函数的定义,用法与StringVar相同。
func BoolVar(p *bool, name string, value bool, usage string)
func DurationVar(p *time.Duration, name string, value time.Duration, usage string)
func Float64Var(p *float64, name string, value float64, usage string)
func Int64Var(p *int64, name string, value int64, usage string)
func IntVar(p *int, name string, value int, usage string)
func StringVar(p *string, name string, value string, usage string)
func Uint64Var(p *uint64, name string, value uint64, usage string)
func UintVar(p *uint, name string, value uint, usage string)
上面列出的函数带有
Var
后缀,表示需要我们自己传递一个变量去接收命令行参数,而flag在这些函数有基础上,封装了下面列表的函数,这些函数没有
后缀,跟上面的函数相比少了一个参数,却多了一个返回值,这个返回值就是接收命令参数的变量指针。
func Bool(name string, value bool, usage string) *bool
func Duration(name string, value time.Duration, usage string) *time.Duration
func Float64(name string, value float64, usage string) *float64
func Int(name string, value int, usage string) *int
func Int64(name string, value int64, usage string) *int64
func String(name string, value string, usage string) *string
func Uint(name string, value uint, usage string) *uint
func Uint64(name string, value uint64, usage string) *uint64
所以我们把上面的示例改写为以下的样子:
host := flag.String("host", "", "数据库地址")
dbName := flag.String("db_name", "", "数据库名称")
user := flag.String("user", "", "数据库用户")
password := flag.String("password", "", "数据库密码")
port := flag.Int("port", 3306, "数据库端口")
fmt.Printf("数据库地址:%s\n", *host)
fmt.Printf("数据库名称:%s\n", *dbName)
fmt.Printf("数据库用户:%s\n", *user)
fmt.Printf("数据库密码:%s\n", *password)
fmt.Printf("数据库端口:%d\n", *port)
另外,运行程序时,在后面跟上
-h
--help
来查看命令的参数选项,如:
go run main.go --help
Usage of main:
-db_name string
数据库名称
-host string
数据库地址
-password string
数据库密码
-port int
数据库端口 (default 3306)
-user string
数据库用户
flag支持以下三种命令行格式,参数前面的
也可以换成
--
,在flag库中,
并不是表示长选项的意思。
cmd -flag
cmd -flag=x
cmd -flag x
第一种只用布尔值的选项,如果该参数出现,则为true,不出则为默认值,而其他数据类型不能使用这种格式传值。
第二种可适用任何类型,因此也是最常用的格式。
第三种不可用于布尔值的选项。
flag在解析参数时,如果遇到第一个非选项参数(不是以-或--开头的)或终止符--,就会停止解析,
比如上面的示例中,我们将运行命令改成下面的样子:
go run main.go -host=localhost noflag -user=test -password=123456 -db_name=test -port=3306
运行结果如下,可以看到解析-host参数之后遇到了noflag这样的非选项参数,flag就停止解析了,所以后面的参数都只输出了默认值。
数据库名称:
数据库用户:
数据库密码:
整数类型的参数可以接收十进制、八进制,十六进制的参数,布尔型可以接收下面列出参数
1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False
Duration
类型的参数接收可以被
time.ParseDuration()
解析的参数。
我们知道flag库是用于命令行解析的,但其内部是怎么解析的呢?下面我们来分析一下
一个命令行参数包含以下四个部分:
接收参数的变量
参数名称
默认值
参数说明
所以flag设置命令行参数的函数有四个参数,比如:
var p int
flag.IntVar(&p,"port",3306,"数据库端口")
flag内部有一个名称CommandLine的变量,其类型为FlagSet,如:
var CommandLine = NewFlagSet(os.Args[0], ExitOnError)
FlagSet就是一个命令行参数的集合体,当我们调用诸如
IntVar
这类的函数时,就是将命令行的
等信息告诉flag库,而flag内部会让CommandLine来处理,用这些信息创建Flag类型的变量,将添加到这个集合体中。
flag := &Flag{name, usage, value, value.String()}
最后,当我们调用flag.Parse函数时,实际就是调用FlagSet结构体的Parse函数将命令参数解析到变量中,flag.Parse函数代码如下:
func Parse() {
CommandLine.Parse(os.Args[1:])
从上面的代码我们也可以看出来,FlagSet的Parse函数最终是通过获取os.Args数组的数据来解析命令行参数的。
即然我们知道flag是通过类型为FlagSet的变量CommandLine来处理命令行参数的,那其实我们也可以自己创建一个FlagSet类型的变量来处理命令行参数,
所以我们可以将上面的例改成下面的样子:
"os"
//自己创建一个命令行参数的集合
var flagSet = flag.NewFlagSet("my flag", flag.ExitOnError)
host := flagSet.String("host", "", "数据库地址")
dbName := flagSet.String("db_name", "", "数据库名称")
user := flagSet.String("user", "", "数据库用户")
password := flagSet.String("password", "", "数据库密码")
port := flagSet.Int("port", 3306, "数据库端口")
//解析命令行参数,从os.Args的第二个元素开始,第一个元素是命令本身
flagSet.Parse(os.Args[1:])
另外,我们已经知道了flag解析参数的来源是os.Args这样的字符串数组,那我们也可以模拟一个这样的数组,将数组解析到变量之中,而不需要去解析os.Args数组,
下面的例子就是这样做的:
//模拟os.Args数组,定义一个参数数组
var params = []string{"-host", "127.0.0.1", "-db_name", "test", "-user", "test", "-password", "abcdef", "-port", "13306"}
//解析自定义的参数数组
flagSet.Parse(params)
运行程序,在命令后面不需要跟命令行参数,如下:
go run main.go
运行后结果如下:
数据库地址:127.0.0.1
数据库密码:abcdef
数据库端口:13306
如果flag提供的数据类型不能满足我们的需要,我们也可以自定义类型,自定义类型需要实现flag中的Value接口,该接口定义如下:
type Value interface {
String() string
Set(string) error
Value
类型的String()用于打印数值,而Set方法则用于flag包将命令行参数设置到
类型中。
下面是一个自定义类型的示例程序:
"strings"
type Users []string
func (u *Users) Set(val string) error {
*u = strings.Split(val, ",")
return nil
func (u *Users) String() string {
str := "["
for _, v := range *u {
str += v
return str + "]"
var u Users
flag.Var(&u, "u", "用户列表")
for _, v := range u {
fmt.Println(v)
运行结果:
 go run main.go -u=小明,小张,小红,小刚
小明
小张
小红
小刚
从上面的示例中我们可以总结自定义类型的几个步骤:
定义一个实现flag.Value接口的类型,并实现String和Set方法。
使用flag.Var函数将类型绑定到类型参数。
调用flag.Parse()解析命令行参数。
我们在使用Linux命令的时候,发现很多命令的参数是有分短选项和长选项的,不过flag库并不支持短选项;当然也有变通的方式,比如我们可以自己定义一个长选项和短选项,
如:
var port int
flag.IntVar(&port, "p", 3306, "数据库端口")
fmt.Println(port)
上面的程序中,我们定义了
两个参数,并将其绑定到变量
,因此通过下面两条命令都可以获取参数:
$ go run main.go -p 111
$ go run main.go -port 111
在这篇文章中,我们全面讲解了flag库,看完这篇文章,相信你可以学习到以下几点:
在Go程序员中如何使用flag库解析命令行参数。
flag库解析命令行参数的原理。
怎么让flag库支持我们自定义的数据类型。
怎么定义命令行参数短选项。
到此这篇关于关于Golang标准库flag的全面讲解的文章就介绍到这了,更多相关Golang标准库flag内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
您可能感兴趣的文章:
深入探究Golang中flag标准库的使用
Golang flag包的具体使用
深入解析golang中的标准库flag
Go语言库系列之flag的具体使用
golang flag简单用法
Go语言中使用flag包对命令行进行参数解析的方法
简单聊聊Golang中Flag包的具体使用
标准库
flag
相关文章
Go语言kafka生产消费消息实例搬砖
这篇文章主要为大家介绍了Go语言kafka生产消费消息的实例搬砖,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-06-06
Go标准库http server优雅启动深入理解
这篇文章主要介绍了Go标准库http server优雅启动深入理解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2024-01-01
详解Go中Set的实现方式
这篇文章主要介绍了详解Go中Set的实现方式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2019-09-09
golang中json小谈之字符串转浮点数的操作
这篇文章主要介绍了golang中json小谈之字符串转浮点数的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
2021-03-03
golang结合mysql设置最大连接数和最大空闲连接数
本文介绍golang 中连接MySQL时,如何设置最大连接数和最大空闲连接数,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
2022-02-02
Golang 之区分类型别名与类型定义的方法
这篇文章主要介绍了Golang 之区分类型别名与类型定义的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
2021-02-02
golang 获取明天零点的时间戳示例
今天小编就为大家分享一篇golang 获取明天零点的时间戳示例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
2018-05-05
Go结构体SliceHeader及StringHeader作用详解
这篇文章主要为大家介绍了Go结构体SliceHeader及StringHeader作用的功能及面试官爱问的实际意义详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2022-07-07
Go语言实现切片增删改查的示例代码
这篇文章主要为大家详细介绍了Go语言中切片的使用(增删改查),文中的示例代码讲解详细,对我们学习Go语言有一定的帮助,需要的可以参考一下
2022-04-04
Golang int函数使用实例全面教程
这篇文章主要为大家介绍了Golang int函数使用实例全面教程详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
2023-10-10
最新评论
大家感兴趣的内容
Goland激活码破解永久版及安装详细教程(亲测可以)
Go语言string,int,int64 ,float之间类
Go语言中的Array、Slice、Map和Set使用详解
Go语言的GOPATH与工作目录详解
Go语言转换所有字符串为大写或者小写的方法
Go语言interface详解
五步让你成为GO 语言高手
Go语言命令行操作命令详细介绍
Go语言编程中字符串切割方法小结
10
我放弃Python转Go语言的9大理由(附优秀书籍推荐)
最近更新的内容
详解如何使用Go模块进行依赖管理
go语言if/else语句简单用法示例
Go语言hello world实例
golang的空标识符理解
golang实现通过smtp发送电子邮件的方法
一文详解golang延时任务的实现
golang 函数返回chan类型的操作
Go 字符串格式化的实例代码详解
Go语言反射reflect.Value实现方法的调用
探索Golang Redis实现发布订阅功能实例
常用在线小工具
关于我们
广告合作
联系我们
免责声明
网站地图
投诉建议
在线投稿
©CopyRight 2006-2024 JB51.Net Inc All Rights Reserved. 脚本之家 版权所有