Golang:Cobra安装与使用

引子

最近在做一个基于Golang的CLI程序,索性便将自己探索出来的经验写下与诸位分享,如果更好的方法也希望大家能告知,共同进步

Cobra安装

大部分教程都是直接告诉我们,我们只需要在有go的环境下,输入

$ go get -v github.com/spf13/cobra/cobra

便可以顺顺利利的安装。然而,现实与理想还是有差距的。许多同学都因为某些被墙的链接而停在了某一步骤。解决方法当然是有的。
请在 $GOPATH/src/golang.org/x 目录下用 git clone 下载 sys 和 text 项目,然后使用 go install github.com/spf13/cobra/cobra, 安装后在 $GOBIN 下出现了cobra 可执行程序。如果你没有配置 $GOBIN,那么可以在$GOPATH/bin 下找到 cobra的可执行软件。(这个方法适用于大部分出现类似问题的第三方包下载)

Cobra使用

生成项目文件

cobra程序只能在GOPATH之下使用,所以首先你需要进入到GOPATH的src目录之下,在该目录下,输入:

$GOPATH/src/$ cobra init demo

在你的当前目录下,应该已经生成了一个demo文件夹:

demo
├── cmd
│   └── root.go
├── LICENSE
└── main.go

上述便是该文件夹的结构,我们可以进去该文件夹,运行:

$ go run main.go

应该会打印如下结果:

A longer description that spans multiple lines and likely contains examples and usage of using your application. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.

至此,我们的cobra项目便已经生成完毕

添加子命令

这里我们先讲述如何添加子命令,再说明如何添加参数。
实际操作其实cobra都能帮你完成,假设我们现在需要添加一个test参数,在项目文件夹下命令行输入

../src/demo$ cobra add test

执行完成后,现在我们的demo结构应该是:

.
├── cmd
│   ├── root.go
│   └── test.go
├── LICENSE
└── main.go

可以看到,在cmd目录下,已经生成了一个与我们命令同名的go文件,你也许已经猜测到,与该命令有关的操作也正是在此处实现。现在执行这个子命令

$ go run main.go test

命令行将会打印输出test called
那么现在又有一个问题,如果我们想添加子命令下的子命令呢?
现在让我们打开test.go,你应该看到如下的文件内容:

// Copyright © 2017 NAME HERE 
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
    "fmt"

    "github.com/spf13/cobra"
)

// testCmd represents the test command
var testCmd = &cobra.Command{
    Use:   "test",
    Short: "A brief description of your command",
    Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Println("test called")
    },
}

func init() {
    RootCmd.AddCommand(testCmd)

    // Here you will define your flags and configuration settings.

    // Cobra supports Persistent Flags which will work for this command
    // and all subcommands, e.g.:
    // testCmd.PersistentFlags().String("foo", "", "A help for foo")

    // Cobra supports local flags which will only run when this command
    // is called directly, e.g.:
    // testCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

你会发现,在init中有一句 RootCmd.AddCommand(testCmd) 这个RootCmd是什么?打开root.go,你会发现RootCmd其实就是我们的根命令。我相信机智的同学已经猜出来我们添加子命令的子命令的方法了。现在让我们在cmd目录下新建testson.go文件,把test.go的内容复制进去,并修改为如下内容:

// Copyright © 2017 NAME HERE 
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package cmd

import (
    "fmt"

    "github.com/spf13/cobra"
)

// testCmd represents the test command
var testsonCmd = &cobra.Command{
    Use:   "testson",
    Short: "A brief description of your command",
    Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Println("testson called")
    },
}

func init() {
    testCmd.AddCommand(testsonCmd)

    // Here you will define your flags and configuration settings.

    // Cobra supports Persistent Flags which will work for this command
    // and all subcommands, e.g.:
    // testCmd.PersistentFlags().String("foo", "", "A help for foo")

    // Cobra supports local flags which will only run when this command
    // is called directly, e.g.:
    // testCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

现在在命令行运行:

go run main.go test testson

当你看到testson called,恭喜你,子命令添加成功!否则你应当检查你的代码是否有误。

添加参数

我相信从init函数中的注释中,你已经得到了足够多的信息来自己操作添加flag,但我还是想要啰嗦两句。首先是persistent参数,当你的参数作为persistent flag存在时,如注释所言,在其所有的子命令之下该参数都是可见的。而local flag则只能在该命令调用时执行。可以做一个简单的测试,在test.go的init函数中,添加如下内容:

testCmd.PersistentFlags().String("foo", "", "A help for foo")
testCmd.Flags().String("foolocal", "", "A help for foo")

现在在命令行 go run main.go test -h 得到如下结果:

../src/demo$ go run main.go test -h
A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.

Usage:
  demo test [flags]
  demo test [command]

Available Commands:
  testson     A brief description of your command

Flags:
      --foo string        A help for foo
      --foolocal string   A help for foo
  -h, --help              help for test

Global Flags:
      --config string   config file (default is $HOME/.demo.yaml)

Use "demo test [command] --help" for more information about a command.

接着让我们再运行 go run main.go test testson -h

../src/demo$ go run main.go test testson -h
A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.

Usage:
  demo test testson [flags]

Flags:
  -h, --help   help for testson

Global Flags:
      --config string   config file (default is $HOME/.demo.yaml)
      --foo string      A help for foo

可以发现在Gloabal Flags的变化。test作为root的子命令,仍然可以使用root的persistent flag-> config(可以查看root.go),而testson作为test的子命令,不仅可以使用test的persistent flag-> fool, 也可以使用test父命令的persistent flag。从而我们可以直观的看出persistent的作用范围是该命令之后的所有子命令。接下来你可能会问,那flag支持什么类型参数?答案是,请查看官方文档
请注意,cmd.Flags().String()与 cmd.Flags().StringP()是不一样的。假如我们在test.go的init下增加如下两行:

testCmd.Flags().String("f", "", "test")
testCmd.Flags().StringP("aaa", "a", "", "test")

前者调用需要如下形式:

go run main.go test --f

后者有如下两种形式调用:

go run main.go test --aaa
go run main.go test -a

另外可以额外告知你如何使用slice作为参数,如[]string:

testCmd.Flags().StringSliceP("arr","r", nil, "test arr")

调用该参数的方法为:

go run main.go test -r "a,b,c"

请不要键入多余空格(除非确实需要键入),也不要使用空格替代逗号作为分割符

获取参数值

在知道了如何设置参数后,我们的下一步当然便是需要在运行时获取该参数的值。现在让我们把注意力放到test.go的此部分:

var testCmd = &cobra.Command{
    Use:   "test",
    Short: "A brief description of your command",
    Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

Cobra is a CLI library for Go that empowers applications.
This application is a tool to generate the needed files
to quickly create a Cobra application.`,
    Run: func(cmd *cobra.Command, args []string) {
        fmt.Println("test called")
    },
}

在给你讲述如何获取参数值之前,我希望你能先学习cobra.Command结构,相信我,这样并不会浪费你的时间。如果你只希望知道如何获取参数值,那么也可以在以后再学习。
让我们把注意力重新放到上面的代码上。我们也很容易可以猜测到Use,Short,Long三个参数的作用,这里便不做阐述(你可以参照添加子命令的子命令的部分的输出)。显而易见,我们应该在Run这里来获取参数并执行我们的命令功能。获取参数其实也并不复杂。以testCmd.Flags().StringP("aaa", "a", "", "test")此为例,我们可以在Run函数里添加:

str := testCmd.Flags().GetString("aaa")

这样便可以获取到该参数的值了,其余类型参数获取也是同理。如 testCmd.Flags().GetStringSlice("arr"),规律并不难见。

End

至此,你已经有了利用cobra构建一个cli程序的基本能力了。当然,更为复杂的方法在这里并没有介绍(因为我没用到:)),你可以通过官方文档(推荐)或者他人文档来学习更为复杂的应用。

你可能感兴趣的:(golang语言学习路线)