前言

啥是带Flag,就是例如在Linux下运行某个命令

rm -rf /*

而这个命令的-rf就是rm这个命令的flag。
一个cli控制台软件一般来说需要很多功能,而在没有图形界面的情况下,软件要通过执行命令去运行,所以一般会通过flag来定义这个软件以什么样的方式和参数去运行。
而啥事子命令,其实简单来说就是主程序中的子项,用来区分不同功能,例如在centos下的包管理器dnf:

dnf install xxx  安装xxx
dnf remove xxx   卸载xxx

而这个时候,installremove都是dnf的子命令,用于区分dnf中不同功能的子项

代码展示

这里用golang编写一个简单的带flag控制的cli控制台工具的源码,仅供参考:

package main

import (
    "fmt"
    "os"

    "gopkg.in/urfave/cli.v1"
)

func main() {
    hello := cli.NewApp()
    hello.Usage = "This is a program which use to say hello and goodbye"
    hello.Commands = []cli.Command{
        {
            Name:      "hello",
            ShortName: "h",
            Usage:     "say hello",
            Flags: []cli.Flag{
                cli.StringFlag{
                    Name:  "method,m",
                    Usage: "Method of say hello",
                    Value: "Hello,",
                },
                cli.StringFlag{
                    Name:  "name,n",
                    Usage: "Input your name",
                    Value: "Gxr",
                },
            },
            Action: func(c *cli.Context) error {
                method := c.String("method")
                uname := c.String("name")
                sum := method + uname
                fmt.Println(sum)
                return nil
            },
        },
        {
            Name:      "bye",
            ShortName: "b",
            Usage:     "say goodbye",
            Flags: []cli.Flag{
                cli.StringFlag{
                    Name:  "method,m",
                    Usage: "Method of say goodbye",
                    Value: "goodbye,",
                },
                cli.StringFlag{
                    Name:  "name,n",
                    Usage: "Input your name",
                    Value: "Gxr",
                },
            },
            Action: func(c *cli.Context) error {
                method := c.String("method")
                uname := c.String("name")
                sum := method + uname
                fmt.Println(sum)
                return nil
            },
        },
    }
    hello.Run(os.Args) 
}

解释阶段

此处以上面代码结构为例

代码执行

假设上面的代码编译成一个hello的可执行文件,放到Linux中执行

hello hello -m 你好, -n G小R

那么输出的内容就是:

你好,G小R

代码结构

1.需要引包:"gopkg.in/urfave/cli.v1",osfmt
2.先实例化一个控制台应用:

实例名 := cli.NewApp()

3.然后给控制台应用的功能做解释:

实例名.Usage = "xxxx"

4.接着开始做命令的设定:

实例名.Commands = []cli.Command{}

此处要注意的是,[]cli.Command{}属于一个结构体数组,这意味着这个可以做多个命令的定义
5.定义相关的命令
一个[]cli.Command{}里面至少要有以下内容

Name:      "",  //这是子命令的名称,例如上面的hello hello,第一个hello是主程序名,第二个hello是子命令
ShortName: "",  //这是子命令的缩写,为了方便命令执行不需要写太多内容,例如hello h和hello hello是一样的
Usage:     "",  //命令的用途,基本上是自定义的
Flags: []cli.Flag{  //定义命令的flag
    cli.类型Flag{ //此处的 类型Flag ,“类型”二字是可更换的,例如有IntFlag,StringFlag,可以参考文档
        Name: "" //Flag的名称,详写和缩写写在一起,用逗号隔开
        Usage: "" //Flag的用途,和上面的Usage一致
        Value:   //flag的参数值(字符串类型要加""),此处为默认值,命令执行不做指定的时候把默认值传到Action
    },
},
Action: func(c *cli.Context) error { //命令的执行函数,用匿名函数,此格式固定,函数内容可以随意发挥
    uname := c.String("")  //获取flag的value值,""内是Flag的Name参数
    ...
    return nil
},

6.执行命令

实例名.Run(os.Args)

这一条命令必须添加到最后,否则执行失败。

参考文档

cliv1包标准库Context项