Go语言库系列之flag

背景

终端(命令行)操作是程序员的必备技能,但是你知道怎么通过golang制作出如下命令吗?

$ flag girl -h
Usage of girl:
  -height int
        身高 (default 140)
$ flag girl --height 170
恭喜你获得了身高 170 的女朋友

极速上手

整个实现非常简单,只需要5个步骤

第一步,引库

import "flag"

第二步,定义变量

定义该变量的作用是存储命令行参数传来的值

var height int

第三步,配置命令信息

main
函数或 init
函数中加入

flag.IntVar(&height, "height", 140, "身高")
  • 第一个参数是定义的变量引用
  • 第二个参数:命令的名称
  • 第三个参数:命令参数的默认值
  • 第四个参数:命令的用法提示

第四步,解析参数

main
函数中追加

flag.Parse()

第五步,打印变量

main
函数中追加

fmt.Println("恭喜你获得了身高", height, "的女朋友")

大功告成,感兴趣的同学可以自行测试。

完整代码

package main

import (
    "flag"
    "fmt"
)

var height int

func main() {
    flag.IntVar(&height, "height", 140, "身高")
    flag.Parse()
    fmt.Println("恭喜你获得了身高", height, "的女朋友")
}

高手进阶

支持多种执行方式

在终端执行时,以下几种传参方式都被支持

$ girl -height 170
$ girl --height 170
$ girl --height=170
$ girl -height=170

支持多种参数值类型

目前支持字符串、布尔、整型、浮点、时间等多种类型,完全该所有场景。

布尔类型支持多种写法

虽然布尔只有 true
false
,但写法却可以各种变种,非常骚气,支持的写法有

1, 0, t, f, T, F, true, false, TRUE, FALSE, True, False

隐式处理接收的参数值

如果我要悄悄地把传入身高减去5厘米怎么办?

第一步,定义一个 height
类型

type height int

第二步,实现 flag.Value
接口的两个方法

func (h *height) String() string {
    return fmt.Sprint(*h)
}

func (h *height) Set(value string) error {
    valueInt, _ := strconv.Atoi(value)
    *h = height(valueInt - 5)
    return nil
}

String
方法用于格式化值, Set
方法用于处理变量设置时候的逻辑。

第三步,定义height类型变量

var heightFlag height

第四步,主函数配置及解析

func main() {
    flag.Var(&heightFlag, "height", "身高")
    flag.Parse()
    fmt.Println(heightFlag)
}

代码与极速上手中的主函数内容大致相同,只是调用了 flag.Var
方法,该方法不需要传入默认值。