美文网首页Golang相关
Golang Cobra的使用

Golang Cobra的使用

作者: 李小西033 | 来源:发表于2019-12-14 11:25 被阅读0次

    在阅读Docker源码时发现,Docker命令行是使用cobra库创建的,为了更好的理解源码,先来熟悉一下Cobra。
    Cobra既是一个用来创建强大的现代命令行应用的库,又是一个用来生成应用和命令文件的脚手架。
    很多流行的Go项目都使用Cobra,例如Kubernetes, Hugo, rkt, etcd, Moby (former Docker), Docker (distribution), OpenShift, Delve, GopherJS, CockroachDB, Bleve, ProjectAtomic (enterprise), Giant Swarm's gsctl, Nanobox/Nanopack, rclone, nehm, Pouch, Istio, Prototool, mattermost-server, Gardener, Linkerd等。

    概念

    命令(Commands),参数(Args)和标识(Flags)是Cobra重要的三个概念。

    • 命令(Commands)代表动作
    • 参数(Args)代表事件
    • 标示(Flags)是对动作的修饰
      好的命令行应该像自然语句一样流畅,让用户一眼就明白其作用。
      例如以下例子,docker是根命令,pull是命令。
    docker pull hello-world
    

    命令(Commands)

    下列代码将docker作为根命令,pull作为其子命令。

    package main
    import (
        "fmt"
        "strings"
        "github.com/spf13/cobra"
    )
    
    func main() {
        var cmdPull = &cobra.Command{
            Use:   "pull [OPTIONS] NAME[:TAG|@DIGEST]",
            Short: "Pull an image or a repository from a registry",
            Run: func(cmd *cobra.Command, args []string) {
                fmt.Println("Pull: " + strings.Join(args, " "))
            },
        }
    
        var rootCmd = &cobra.Command{Use: "docker"}
        rootCmd.AddCommand(cmdPull)
        rootCmd.Execute()
    }
    

    运行结果

    Commands.png
    当然,这里只是展示cobra的基本使用方法,docker命令的具体实现见源码https://github.com/docker/cli/blob/v19.03.5/cmd/docker/docker.go

    参数(Args)

    通过Command的Args属性对参数进行校验。

    标示(Flags)

    标示分为全局标示(Persistent Flags)和局部标示(Local Flags)

    全局标示(Persistent Flags)

    全局标示(Persistent Flags)会作用于其指定的命令与指定命令所有的子命令。
    例如在上例中加入一行代码

    rootCmd.PersistentFlags().BoolP("help", "h", false, "Print usage")
    
    image.png

    局部标示(Local Flags)

    局部标示(Local Flags)仅作用于其指定命令。
    例如docker image inspect命令的源码中定义了局部标示-fhttps://github.com/docker/cli/blob/v19.03.5/cli/command/image/inspect.go

    flags := cmd.Flags()
        flags.StringVarP(&opts.format, "format", "f", "", "Format the output using the given Go template")
    
    image.png

    注:Docker自定义了命令行模版,所以Flags在docker命令中显示的是Options
    https://github.com/docker/cli/blob/v19.03.5/cli/cobra.go#L304

    Demo

    参照Docker源码,实现类似docker ps的功能:返回运行中的容器ID

    package main
    
    import (
        "fmt"
        "context"
        "github.com/docker/docker/api/types"
        "github.com/docker/docker/client" // v1.13.1
        "github.com/spf13/cobra"
    )
    
    
    func runPs(dockerCli *client.Client) {
        containers, err := dockerCli.ContainerList(context.Background(), types.ContainerListOptions{})
        if err != nil {
            panic(err)
        }
    
        fmt.Println("运行中的容器ID:")
        for _, container := range containers {
            fmt.Printf("%s \n", container.ID[:10])
        }
    
    }
    
    
    func main() {
        dockerCli, _ := client.NewEnvClient()
    
        // 定义ps命令
        var cmdPs = &cobra.Command{
            Use:              "ps",
            Short:            "List containers",
            Run: func(cmd *cobra.Command, args []string)  {
                runPs(dockerCli)
            },
        }
        // 定义根命令
        var rootCmd = &cobra.Command{Use: "play_docker"}
        // 加入ps命令
        rootCmd.AddCommand(cmdPs)
        // 初始化cobra
        rootCmd.Execute()
    }
    

    执行我们的山寨命令行./play_docker ps看到返回的结果和docker ps是一致的😊

    image.png

    相关文章

      网友评论

        本文标题:Golang Cobra的使用

        本文链接:https://www.haomeiwen.com/subject/hmjcnctx.html