andy27367451 发表于 2018-9-21 06:50:22

Golang: Cobra命令行参数库的使用

  将cobra下载到 $GOPATH,用命令:
  

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

  然后使用 go install github.com/spf13/cobra/cobra, 安装后在 $GOBIN 下出现了cobra 可执行程序。如果你没有配置 $GOBIN,那么可以在$GOPATH/bin 下找到 cobra的可执行软件。
  cobra程序只能在GOPATH之下使用,所以首先你需要进入到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的可执行命令生成示例代码,只想在项目使用其库代码,则上面的内容可以忽略。
  附 demo 文件夹的内容:
  cmd/root.go:
  

// Copyright © 2018 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"
  "os"
  

  homedir "github.com/mitchellh/go-homedir"
  "github.com/spf13/cobra"
  "github.com/spf13/viper"
  
)
  

  
var cfgFile string
  

  
// rootCmd represents the base command when called without any subcommands
  
var rootCmd = &cobra.Command{
  Use:   "demo",
  Short: "A brief description of your application",
  Long: `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.`,
  // Uncomment the following line if your bare application
  // has an action associated with it:
  //    Run: func(cmd *cobra.Command, args []string) { },
  
}
  

  
// Execute adds all child commands to the root command and sets flags appropriately.
  
// This is called by main.main(). It only needs to happen once to the rootCmd.
  
func Execute() {
  if err := rootCmd.Execute(); err != nil {
  fmt.Println(err)
  os.Exit(1)
  }
  
}
  

  
func init() {
  cobra.OnInitialize(initConfig)
  

  // Here you will define your flags and configuration settings.
  // Cobra supports persistent flags, which, if defined here,
  // will be global for your application.
  rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.demo.yaml)")
  

  // Cobra also supports local flags, which will only run
  // when this action is called directly.
  rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
  
}
  

  
// initConfig reads in config file and ENV variables if set.
  
func initConfig() {
  if cfgFile != "" {
  // Use config file from the flag.
  
      viper.SetConfigFile(cfgFile)
  } else {
  // Find home directory.
  home, err := homedir.Dir()
  if err != nil {
  fmt.Println(err)
  os.Exit(1)
  }
  

  // Search config in home directory with name ".demo" (without extension).
  
      viper.AddConfigPath(home)
  viper.SetConfigName(".demo")
  }
  

  viper.AutomaticEnv() // read in environment variables that match
  

  // If a config file is found, read it in.
  if err := viper.ReadInConfig(); err == nil {
  fmt.Println("Using config file:", viper.ConfigFileUsed())
  }
  
}
  

  main.go:
  

// Copyright © 2018 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 main
  

  
import "demo/cmd"
  

  
func main() {
  cmd.Execute()
  
}
  


添加子命令
  实际操作其实cobra都能帮你完成,假设我们现在需要添加一个test参数,在项目文件夹下命令行输入:
  

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文件,项目文件结构为:
  

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

  把test.go的内容复制进去,并testson.go文件修改为如下内容:
  cmd/testson.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 得到如下结果:
  

$ 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
  demo test
  

  
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 --help" for more information about a command.  

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

$ 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:
-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")  },
  
}
  

  让我们把注意力重新放到上面的代码上。我们也很容易可以猜测到Use,Short,Long三个参数的作用,这里便不做阐述(你可以参照添加子命令的子命令的部分的输出)。显而易见,我们应该在Run这里来获取参数并执行我们的命令功能。获取参数其实也并不复杂。以testCmd.Flags().StringP("aaa", "a", "", "test")此为例,我们可以在Run函数里添加:
  

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

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


页: [1]
查看完整版本: Golang: Cobra命令行参数库的使用