一、大多数后端程序员多多少少都要和服务器打交道,服务器大多通过命令行去管理,想必大家在大家敲郭不少类似于 git --version的命令吧。可能你会好奇它是如何实现的。下面我将通过使用go语言的flag包实现类似于git --version这样的命令。
二、go flag
go提供了flag包帮助我们实现解析命令行参数的功能
看个简单的例子
package main
import (
"flag"
"fmt"
"strconv"
)
func FlagVal() *int{
n := flag.Int("version", 250, "help")
return n
}
func main() {
s := myflag.FlagVal()
flag.Parse()
fmt.Println(*s)
}
flag.Int的第一个参数是命令行参数名称,如上 git --version 那么写version即可。
第二个参数是默认值,当 --version 后面不加东西时,就会输出默认的250。
第三个参数usage,
if name == "help" || name == "h" { // special case for nice help message.
f.usage()
return false, ErrHelp
}
其实是当 --name 是help或者是h的时候输出(usage()里还有很多其他的处理逻辑,这里就不展开了),git在输入了git --h后
类似于此地的usage。
运行代码
$ go build main.go
$./main
$250
$./main --version 20
$20
直接运行程序就会输出默认值250,正常传参则输出参数值,
flag.Int返回一个指针类型,打印的时候不要忘记加*
注意这里用的时flag.Int()也就是说这个值只能是整型形式,类似的有
flag.String,flag.Bool,flag.Float64。
另外这里–version也可以写成-version,version=
再看另一段flag.IntVar()
这个方法其实和上面的类似,区别在于这个方法没有返回值
且这个方法的第一个参数是一个指针类型即
package main
import (
"flag"
"fmt"
)
func main() {
var m int
flag.IntVar(&m, "m", 250, "help")
flag.Parse()
fmt.Println(m)
}
运行方式与flag.Int一致
自定义flag类型
flag包为我们提供了默认的几种传参类型,flag.Int().flag.String()
其实这些方法都依赖于flag.Var()自定义类型方法,先上代码
type newValue int
func NValue(val int, p *int) *newValue{
*p = val
//这里的意思是将val值重置类型为newValue的指针类型类似于(*int)(int)
return (*newValue)(p)
}
//set方法在flag.Parse中会调用
func (n *newValue) Set (val string) error{
v ,_:= strconv.Atoi(val)
*n = newValue(v)
return nil
}
//string方法是go接口方法用于输出类型的默认信息实现了go的Stringer接口
func (n *newValue) String () string {
return strconv.Itoa(int(*n))
}
//自定义flag类型使用flag.Var方法,该方法的第一个参数是一个指针类型
//这个类型需要实现flag中的Value接口即 实现Set(val string) error 以及String()方法
func FlagVar(name string, n int) *int{
i := new(int)
flag.Var(NValue(n, i), name, "help")
return i
}
我们定义一个新类型,newValue并实现flag包里的Value接口
type Value interface {
String() string
Set(string) error
}
上面的代码实现了类似于flag.Int()的功能,具体方式看注释
每日一包,golang标准库学习~