作者 | 陌无崖
转载请联系授权
Go flag包详解前言入门案例源码包解析定义flag参数完整案例
相信大家都用到过命令行工具。尤其当我们在用Linux进行代码开发时,会使用很多工具,比如下面的这张图。那么自己如何开发一个命令行工具呢?
image.png
在这个案例中我们需要用到Go官方包中的flag解析包。新建一个flag.go
package main
import (
"flag"
"fmt"
)
// 定义命令行参数对应的变量,这三个变量都是指针类型
var cliName = flag.String("name", "nick", "Input Your Name")
var cliAge = flag.Int("age", 28, "Input Your Age")
var cliGender = flag.String("gender", "male", "Input Your Gender")
// 定义一个值类型的命令行参数变量,在 Init() 函数中对其初始化
// 因此,命令行参数对应变量的定义和初始化是可以分开的
var cliFlag int
func Init() {
flag.IntVar(&cliFlag, "flagname", 1234, "Just for demo")
}
func main() {
// 初始化变量 cliFlag
Init()
// 把用户传递的命令行参数解析为对应变量的值
flag.Parse()
// flag.Args() 函数返回没有被解析的命令行参数
// func NArg() 函数返回没有被解析的命令行参数的个数
fmt.Printf("args=%s, num=%d\n", flag.Args(), flag.NArg())
for i := 0; i != flag.NArg(); i++ {
fmt.Printf("arg[%d]=%s\n", i, flag.Arg(i))
}
// 输出命令行参数
fmt.Println("name=", *cliName)
fmt.Println("age=", *cliAge)
fmt.Println("gender=", *cliGender)
fmt.Println("flagname=", cliFlag)
}
编译我们的源文件为二进制
go build .\flag.go
测试以下
.\flag.exe help
image.png
.\flag.exe -name yuwei
image.png
1、通过flag.Xxx()
。Xxx可以指String、Bool、Int等基本数据类型。使用这种方式会相应的返回一个指针。如:
// 定义命令行参数对应的变量,这三个变量都是指针类型
var cliName = flag.String("name", "nick", "Input Your Name")
var cliAge = flag.Int("age", 28, "Input Your Age")
var cliGender = flag.String("gender", "male", "Input Your Gender")
函数中的参数分别代表的含义为:命令行参数、参数的默认值、参数的提示或者解释。
2、通过flag.XxxVar()
方法将flag绑定到一个变量,该种方式返回值类型,如:
var cliFlag int
var flag.IntVar(&cliFlag, "flagname", 1234, "Just for demo")
函数中的参数分别代表的含义为:待赋值的变量、命令行参数、参数的默认值、参数的提示或者解释。
3、通过flag.Var()
绑定自定义类型,自定义类型需要实现Value接口(Receives必须为指针),如下案例
type self struct {
Address string
Area string
}
func (s *self) String() string {
return fmt.Sprintf("%s", *s)
}
func (s *self) Set(value string) error {
return nil
}
var selfFlag self
var flag.Var(&selfFlag, "self", "please input address,area eg: \"beijing china\"")
这里需要注意的是实现接口Value中函数String()代表定义默认值。Set()函数是对参数值的接收对其进行操作。
main.go
package main
import (
"flag"
"fmt"
)
// 定义命令行参数对应的变量,这三个变量都是指针类型
var cliName = flag.String("name", "nick", "Input Your Name")
var cliAge = flag.Int("age", 28, "Input Your Age")
var cliGender = flag.String("gender", "male", "Input Your Gender")
// 定义一个值类型的命令行参数变量,在 Init() 函数中对其初始化
// 因此,命令行参数对应变量的定义和初始化是可以分开的
var cliFlag int
var selfFlag self
func Init() {
flag.IntVar(&cliFlag, "flagname", 1234, "Just for demo")
flag.Var(&selfFlag, "self", "please input address,area eg: \"beijing china\"")
}
func main() {
// 初始化变量 cliFlag
Init()
// 把用户传递的命令行参数解析为对应变量的值
flag.Parse()
// flag.Args() 函数返回没有被解析的命令行参数
// func NArg() 函数返回没有被解析的命令行参数的个数
fmt.Printf("args=%s, num=%d\n", flag.Args(), flag.NArg())
for i := 0; i != flag.NArg(); i++ {
fmt.Printf("arg[%d]=%s\n", i, flag.Arg(i))
}
// 输出命令行参数
fmt.Println("name=", *cliName)
fmt.Println("age=", *cliAge)
fmt.Println("gender=", *cliGender)
fmt.Println("flagname=", cliFlag)
fmt.Println("selfFlag=", selfFlag)
}
type.go
/*
* @Author: your name
* @Date: 2019-11-22 15:38:48
* @LastEditTime: 2019-11-22 19:19:56
* @LastEditors: Please set LastEditors
* @Description: In User Settings Edit
* @FilePath: \GoWebd:\pratice\tflag\demo\type.go
*/
package main
import "fmt"
import "errors"
import "strings"
type self struct {
Address string
Area string
}
func (s *self) String() string {
*s = self{"Beingjing", "China"}
return fmt.Sprintf("%s", *s)
}
func (s *self) Set(value string) error {
if len(value) <= 0 {
return errors.New("参数为空,请输入正确的参数")
}
data := strings.Split(value, " ")
*s = self{
data[0],
data[1],
}
fmt.Println(*s)
return nil
}
运行我们程序
image.png
image.png