golang 命令行 command line (flag,os,arg,args)

目录

  • 1. golang 命令行 command line
    • 1.1. Introduction
    • 1.2. Parsing Arguments from the command line (os package)
      • 1.2.1. Get the number of args
      • 1.2.2. Iterate over all arguments
    • 1.3. Using flags package
      • 1.3.1. Parse Typed Flags
      • 1.3.2. Set flags from the script
      • 1.3.3. Use Reference to arguments (pointers)
      • 1.3.4. Parse Arguments
      • 1.3.5. Get Help text with PrintDefaults
      • 1.3.6. Get the number of arguments
    • 1.4. Conclusion

1. golang 命令行 command line

1.1. Introduction

In the 25th post of the series, we will be taking a look into parsing of command line arguments in golang. We will be exploring how to do the basics of parsing and using the positional parameters or arguments from the command line in the program. By using standard library packages like os and flag, we can make powerful yet easy-to-build CLI apps and programs.

1.2. Parsing Arguments from the command line (os package)

We can use the os package to get the arguments from the command line in a go script. We have to use the Args variable in the os package. The Args variable is a slice of strings which thereby is the parsed arguments from the command line.

  • The first (0 index) Argument is the path to the program
  • The 1st index onwards are the actual arguments passed.
package mainimport ("fmt""os"
)func main() {args := os.Argsfmt.Printf("Type of Args = %T\n", args)fmt.Println(args[0], args[1])
}
$ go run main.go hello
Type of Args = []string
/tmp/go-build1414795487/b001/exe/main hello

In the above example, we can see that the Args is a slice of string and we can get the indices as per the arguments passed from the command line.

If you don’t parse any arguments and access the 1st argument as os.Args[1] it will result in an index out of range error. So, you need to first check if the argument is parsed and set a default value otherwise.

package mainimport ("fmt""os""strconv"
)func main() {var port intvar err errorif len(os.Args) > 1 {port, err = strconv.Atoi(args[1])if err != nil {panic(err)}} else {port = 8000}fmt.Println(port)
}
$ go run main.go
8000$ go run main.go 7000
7090$ go run main.go h
panic: strconv.Atoi: parsing "h": invalid syntax

In the above example, we have declared the port variable as an integer and tried to see if we had an argument parsed from the command line using the len function and if there was a variable, we will simply cast it into an integer using the strconv.Atoi function. If there are any errors in the process, we log an error message and panic out of the program. So, this is how we can set default values or check for any arguments from the command line in golang.

1.2.1. Get the number of args

We can use the len function with the Args slice to get the total number of arguments from the command line. To ignore the first argument which would be the path to the program, we simply can slice the first element as os.Args[1:] . This will slice the list of the arguments from the first index till the last element in the slice.

package mainimport ("fmt""os"
)func main() {total_args := len(os.Args[1:])fmt.Println("Total Args =", total_args)
}
$ go run main.go hello world 56Total Args = 3

This will simply give us the number of arguments passed from the command line, excluding the first(0th) argument which is the default argument as the execution path of the current program.

1.2.2. Iterate over all arguments

We can use the simple for loop with range over the os.Args or os.Args[1:] for iterating over each of the arguments passed from the command line.

package mainimport ("fmt""os"
)func main() {for n, args := range os.Args {fmt.Println("Arg", n, "->", args)}/* // For excluding the 0th argumentfor n, args := range os.Args[1:] {fmt.Println("Arg", n, "->", args)}*/
}
$ go run main.go hello world 56
Arg 0 -> /tmp/go-build2248205073/b001/exe/main
Arg 1 -> hello
Arg 2 -> world
Arg 3 -> 56

We can now iterate over the arguments passed from the command line using a simple for loop. We can further process these arguments per the program’s requirements and need.

1.3. Using flags package

Golang has a package in its standard library called flags which allows us to parse flags and arguments from the command line with a lot of built-in features. For instance, a default value is easily parsed with a simple function parameter, help text in case of an error in parsing the arguments or flag, customization and freedom for choosing a data type for the type of argument, and so on. For a bare-bones and quick CLI program, the flag package is a great choice.

1.3.1. Parse Typed Flags

We can use typed flag values using the functions provided in the flags package like IntVar for an integer value, StringVar for string, BoolVar for boolean values and so on. Each function takes in 4 parameters and they set the value of the parsed variable from the parsed argument/flag from the command line.

  • The first parameter is a reference to the variable to store the value.
  • The second parameter is the name of the argument/flag to be read from the command line.
  • The third parameter is the default value of the variable.
  • The fourth parameter is the help text for that argument/flag.

So, let’s take the previous example of port number parsing from the command line. We can use the flag.IntVar(&port, "p", 8000, "Provide a port number") , this will set the value of the variable port from the command line as the value of -p 6789 or the default value as 8000 . The help text will be used if the user has provided a non-integer or an invalid value as an error message.

package mainimport ("flag""fmt"
)func main() {var port intvar dir stringvar publish boolflag.IntVar(&port, "p", 8000, "Provide a port number")flag.StringVar(&dir, "dir", "output_dir", "Directory")flag.BoolVar(&publish, "publish", false, "Publish the article")flag.Parse()fmt.Println(port)fmt.Println(dir)fmt.Println(publish)if publish {fmt.Println("Publishing article...")} else {fmt.Println("Article saved as Draft!")}
}
$ go run flag.go8000
output_dir
false
Article saved as Draft!$ go run flag.go -p 12341234
output_dir
false
Article saved as Draft!$ go run flag.go -p 1234 -dir site_out1234
site_out
false
Article saved as Draft!$ go run flag.go -publish8000
output_dir
true
Publishing article...

So, in the above, example, we have used a few types of values like IntegerVar for port , StringVar for dir , and BoolVar for publish . As explained earlier, the functions take 4 parameters in the same format, the reference to the variable to hold the parsed value, the name of the argument/flag, the default value the variable will hold, and the help text or usage string. The BoolVar is slightly different but it works logically well, if we parse -publish the value will be set as true and false otherwise. You can manually add the value like -publish true and so on but it is not mandatory and understood as true.

In the above example, we have parsed different arguments in the output and displayed the values of these flags. If we don’t specify a value, we can see the default value being parsed, in the case of the bool variable, the default value is taken as false . Hence we can see how easily we can use and parse flags from the command line in golang, it’s simple, quick, and also extensible.

For other data types, the flag package has functions like Float64Var for float64 values, DurationVar for time duration values and TextVar for other types as inferred by the unmarshalling of the text.

1.3.2. Set flags from the script

We can set the value of a flag/argument from the script rather than from the command line using the Set method in the flag package. The Set method takes in two values as parameters the name of the argument and the value of that argument to set as. It returns an error if any arise during the setting of the argument.

package mainimport ("flag""fmt"
)func main() {var port intvar dir stringvar publish boolflag.IntVar(&port, "p", 8000, "Provide a port number")flag.StringVar(&dir, "dir", "output_dir", "Directory")flag.Parse()fmt.Println(port)fmt.Println(dir)flag.Set("dir", "dumps")fmt.Println(dir)
}
$ go run flag.go -p 8080
8080
output_dir
dumps

So, it is clearly visible that the value of an argument can be changed within the script, it also changes the value of the associated variable. Remember, we gave the two-parameter as strings so the first parameter is the name of the argument and not necessarily the variable name.

1.3.3. Use Reference to arguments (pointers)

Also, there are functions like Int , Float64 , String , Bool in the flag package that can allow getting the values of the arguments without using the Parse method. We use the reference of the value stored in as the arguments instead of defining the variables as a data value; we have a pointer to that value of data.

package mainimport ("flag""fmt"
)func main() {port := flag.Int("p", 8000, "Provide a port number")dir := flag.String("dir", "output_dir", "Directory")publish := flag.Bool("publish", false, "Publish the article")help := flag.Bool("help", false, "Help")if *help {flag.PrintDefaults()} else {fmt.Println(*port)fmt.Println(*dir)flag.Set("dir", "dumps")fmt.Println(*dir)fmt.Println(flag.NFlag())fmt.Println(flag.NArg())fmt.Println(*publish)if *publish {fmt.Println("Publishing article...")} else {fmt.Println("Article saved as Draft!")}vals := flag.Args()fmt.Println(vals)}
}
$ go run flag.go -p 80 -dir node_mods 1234
80
node_mods
dumps
2
1
false
Article saved as Draft!
[1234]

As we can it performs the same task, but we have to use pointers as references to the arguments instead of storing them in an actual memory address. We have performed the same set of operations on the arguments and flags as we do with the other examples.

We first, use the Int method or other methods appropriate that String can be used in general use cases, the function returns a reference (memory address) of the actual stored value of the arguments/flag. We can access the value from its memory address using the * operator. We have covered the pointer arithmetic in the last part of the series. When we use *port we get the value from the memory address and thereby we can use it for the required task in the program, we can also store a copy of the variable by creating a new variable with the value of that argument.

1.3.4. Parse Arguments

So, if we want to parse flags, with a single value, we have seen the use of the flag.Args function to get the values of the arguments passed from the command line which don’t have any flag labels attached to them(just raw arguments from the CMD). Just as we used the os.Args variable but this function is much clean and filtered out the path to the program argument. So we can directly have the arguments which are clearly passed by the user from the command line.

package mainimport ("flag""fmt"
)func main() {var port intflag.IntVar(&port, "p", 8000, "Provide a port number")flag.Parse()fmt.Println(port)vals := flag.Args()fmt.Println(vals)
}
$ go run flag.go -p 8123
8123
[]$ go run flag.go -p 8123 1234 hello true
8123
[1234 hello true]$ go run flag.go -p 8123 1234 hello true -p 9823 world
8123
[1234 hello true -p 9823 world]

In the above example, we can see that we have used a few non-flagged arguments from the command line. The return value of the Args function is a slice of string, we can then convert it into appropriate types using type casting and functions. Once the flagged arguments are parsed, if we use the Args function, it won’t be possible to again use flagged arguments in the command line. It will be considered a simple string thereafter.

That’s it from this part. Reference for all the code examples and commands can be found in the 100 days of Golang GitHub repository.

1.3.5. Get Help text with PrintDefaults

We can use the flag.PrintDefaults method for just printing the default values and the help text for the expected arguments from the command line in the script. We can simply use it as a help flag or use it in error messages for guiding the user to the proper arguments and flags.

package mainimport ("flag""fmt"
)func main() {var port intvar help boolflag.IntVar(&port, "p", 8000, "Provide a port number")flag.BoolVar(&help, "help", false, "Help")flag.Parse()if help {flag.PrintDefaults()} else {fmt.Println(port)vals := flag.Args()fmt.Println(vals)}
}
$ go run help.go -hUsage of /tmp/go-build121267600/b001/exe/help:-helpHelp-p intProvide a port number (default 8000)$ go run help.go8000
[]

So, we can see the PrintDefaults function will simply print the helper text for the flags expected in the script and the default value of those flags as well. This can be used to provide a good user-friendly interface for a simple terminal application.

1.3.6. Get the number of arguments

We can use the NFlag method in the flag package. The function returns an integer that indicates a count of the arguments that have been set from the command line.

package mainimport ("flag""fmt"
)func main() {var port intvar dir stringvar publish boolflag.IntVar(&port, "p", 8000, "Provide a port number")flag.StringVar(&dir, "dir", "output_dir", "Directory")flag.Parse()fmt.Println(port)fmt.Println(dir)fmt.Println(flag.NFlag())
}
$ go run flag.go
8000
output_dir
0$ go run flag.go -p 8080 8999 false hello
8080
output_dir
1$ go run flag.go -p 8080 -dir dumps hello 1234
8080
dumps
2

The port flag has been set from the command line, so we just have one argument set, hence the function NFlag returns 1 as the number of set flags.

Also, the NArg method will return an integer that will count the number of arguments that have been provided leaving out the flag arguments.

package mainimport ("flag""fmt"
)func main() {var port intvar dir stringvar publish boolflag.IntVar(&port, "p", 8000, "Provide a port number")flag.StringVar(&dir, "dir", "output_dir", "Directory")flag.Parse()fmt.Println(port)fmt.Println(dir)fmt.Println(flag.NArg())
}
$ go run flag.go 1234
8000
output_dir
1$ go run flag.go -p 8080 -dir dumps hello 1234
8080
dumps
2$ go run flag.go -p 8080 hello 1234 false
8080
dumps
3

In the first example, we don’t have any flag arguments set, we just have one unflagged argument as 1234 , hence the NArg function returns 1 . The second example has 2 values that are not flagged, we have set the values of port and dir as 8080 and dumps respectively, so the remaining unflagged values are hello and 1234 hence the return value as 2 . The third example has 3 unflagged values as hello 1234 false , hence we return 3 .

That’s it from this part. Reference for all the code examples and commands can be found in the 100 days of Golang GitHub repository.

1.4. Conclusion

We have seen how to parse command line arguments in golang with the os and the flag packages. Though these two are not the only options for building CLI applications, they provide a clean and easy-to-start approach, also they come with the standard library which makes it even better as we don’t have to mingle with third-party libraries. We saw the basics of parsing flags and arguments from a command line program.

Thank you for reading. If you have any queries, questions, or feedback, you can let me know in the discussion below or on my social handles. Happy Coding 😃

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/48855.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android JNI系列详解之AS创建Native C++项目

一、前提 Android Studio版本:Android Studio Electric Eel | 2022.1.1 Patch 1 二、创建Native C项目 1.新建项目 2.选择新建Native C项目 3.New Project 4.选择C标准库的支持版本 5.项目自带的默认生成的代码 6.buil.gradle中也自带了CMakeList的配置(…

【ARM64 常见汇编指令学习 20 -- ARM 指令 .include与 .asciz 详细介绍】

文章目录 .include 介绍.asciz 介绍 .include 介绍 在 ARM 汇编语言中,.include 命令用于插入另一个源文件的内容。它的作用类似于 C 语言中的 #include 预处理命令。这个命令通常在源文件的顶部使用,但也可以在任何地方使用。 语法如下: …

冠达管理:股票分红的钱会计算到收益吗?为什么分红之后出现亏损?

我们常说炒股的主要收益来源便是除了高抛低吸赚取差价收益之外,还有参加股票分红取得。那么股票分红的钱管帐算到收益吗?为什么分红之后呈现亏本?下面就由冠达管理为大家剖析: 股票分红的钱管帐算到收益吗? 不会。 股…

变频器和plc之间无线MODBUS通讯

在工业现场由PLC远程控制变频器的应用非常常见,如果挖沟布线不便或者变频器在移动设备上,那么采用无线通讯就是最佳方案。 这里我们选用最常用的三菱 FX2N PLC和三菱变频器为例,并结合日系plc专用无线通讯终端DTD435M来说明PLC与变频器之间的…

iOS swift 类似AirDrop的近场数据传输 MultipeerConnectivity 框架

文章目录 1.github上的demo 1.github上的demo insidegui/MultipeerDemo – github insidegui/MultipeerKit – github

vue中表格数据已更新但界面内容没有更新,修复方案

this.tableData为表格数据,起初表格数据里的结构是固定的比如如下: tableData:[{name:名称‘,age:12}] 初始数据虽然是这样的结构,但有时候结构可能会改{name:名称,age:12,content:内容} 可能要多加一个字段。起初用this.$set以…

生信豆芽菜-信号转导通路相关评分的计算

网址:http://www.sxdyc.com/gradeSigna 1、数据准备 表达谱数据,行为基因,列为样本 2、提交后,等待运行成功即可下载 当然,如果不清楚数据是什么样的,可以选择下载我们的示例数据,也可以关…

生成树协议

生成树协议 生成树协议是一基于OSI网路模型的数据链路层(第二层)通讯协定,用作确保一个无回圈的区域网络环境。通过有选择性地阻塞网络冗余链路来达到消除网络二层环路的目的,同时具备链路的备份功能,又称扩展树协定。…

SQL注入原理

SQL、SQL注入是什么? 结构化查询语言(Structured Query Language,SQL),是一种特殊的编程语言,用于数据库的标准数据查询。1986 年10 月美国国家标准协会对SQL 进行了规范后,以此作为关系型数据库系统的标准语言。1987 …

基于Spring Boot的社区诊所就医管理系统的设计与实现(Java+spring boot+MySQL)

获取源码或者论文请私信博主 演示视频: 基于Spring Boot的社区诊所就医管理系统的设计与实现(Javaspring bootMySQL) 使用技术: 前端:html css javascript jQuery ajax thymeleaf 微信小程序 后端:Java …

【仿写tomcat】一、tomcat工作流程

仿写tomcat 简介tomcat简介流程分析tomcat是怎么和访问者交互的?流程图 简介 作者前不久刚仿写了一个简易的tomcat,在此分享给各位,此篇为对tomcat的简介和流程分析,具体仿写内容后续会贴在这里 扫描java文件,获取带…

Linux 定时任务 crontab 用法学习整理

一、linux版本 lsb_release -a 二、crontab 用法学习 2.1,crontab 简介 linux中crontab命令用于设置周期性被执行的指令,该命令从标准输入设备读取指令,并将其存放于“crontab”文件中,以供之后读取和执行。cron 系统调度进程。…

关于LED电子显示屏幕的显示功能

因为LED显示屏的发光颜色和发光效率与制作LED的材料和工艺相关,目前广泛采用的有红、绿、蓝三种颜色的LED。这些LED的独特之处在于它们工作时需要的电压极低(仅1.5-3V),能够主动发光,并且具有一定的亮度。这亮度可以通…

【面试刷题】——什么是深拷贝和浅拷贝?

深拷贝(Deep Copy)和浅拷贝(Shallow Copy)是在编程中用来描述对象拷贝的两个概念,特别是在涉及对象包含其他对象(如嵌套数据结构、指针等)的情况下。 浅拷贝(Shallow Copy&#xff…

苹果手机桌面APP带云图标有个箭头,过一段时间经常要下载才能使用APP

环境: IPhone 11 IOS13.0 问题描述: 苹果手机桌面APP带云图标有个箭头,过一段时间经常要下载才能使用APP 解决方案: 1.打开设置,往下找到iTunes Store与App Store 2.找到下面卸载未使用的APP 关闭按钮

C 语言学习

数组的指针 在c中&#xff0c;几乎所以使用数组名的表达式中&#xff0c;数组名的值是一个指针常量&#xff0c;也就是数组 第 一个元素的地址。注意这个值是指针常量&#xff0c;不是变量。 int a[10]{ ….....}; int *q; q&a[0] ; <>…

第1步---MySQL安装和配置

第1步---MySQL安装和配置 1.下载地址 MySQL :: Download MySQL Community Server (Archived Versions) 直接下载zip形式的就可以。 2.在bin的同级目录下常见my.ini文件。 输入下面的内容 my.ini中的文本&#xff1a; [mysqld] #设置3306端口 port3306 character-set-server…

线程池一定需要了解的那些事

一、阿里Java开发规范&#xff0c;为啥禁止直接使用Executors创建线程池 newFixdThreadPool 及 singleThreadPool 中默认队列长度为 Integer.MAX_VALUE&#xff0c;如果线程执行比较耗时&#xff0c;执行任务的线程在队列中产生大量堆积&#xff0c;进而有导致虚拟机OOM 的风险…

c#配置提供者

在 C# 中,配置系统是一种用于管理应用程序配置数据的机制。通常情况下,应用程序的配置数据包括连接字符串、应用程序设置、环境变量等。C# 配置系统允许您轻松地读取和使用这些配置数据,而不需要硬编码在代码中。 除了默认的配置提供者外,C# 配置系统还支持其他配置提供者…

关于内存融合cache fusion中锁模式的一些思考

集群中不可能即存在写锁&#xff0c;又存在读锁。这个从读写锁的语义上已经定义。集群中只能存在一个人持有写锁&#xff0c;其他人再申请写锁时必须要释放当前写锁。集群中可能存在多个读锁。集群中存在脏块时&#xff0c;可能存在&#xff08;一个或多个&#xff09;读锁&…