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 <EMAIL ADDRESS>
//
// 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()
}
} 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()
} // 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 <EMAIL ADDRESS>
//
// 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 <EMAIL ADDRESS>
//
// 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 <EMAIL ADDRESS>
//
// 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 [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
$ 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")
},
}
让我们把注意力重新放到上面的代码上。我们也很容易可以猜测到Use,Short,Long三个参数的作用,这里便不做阐述(你可以参照添加子命令的子命令的部分的输出)。显而易见,我们应该在Run
这里来获取参数并执行我们的命令功能。获取参数其实也并不复杂。以testCmd.Flags().StringP("aaa", "a", "", "test")
此为例,我们可以在Run函数里添加:
str := testCmd.Flags().GetString("aaa")
这样便可以获取到该参数的值了,其余类型参数获取也是同理。如 testCmd.Flags().GetStringSlice("arr")
,规律并不难见。
Golang: Cobra命令行参数库的使用的更多相关文章
- 微软官方的.net命令行参数库
虽然现在是图形化大行其道的时代,但让程序支持命令行启动对于专业的领域还是有不少需求的..net本身并没有内置对命令行解析的支持,我之前就写过一篇文章让.Net程序支持命令行启动介绍了几个第三方的命令行 ...
- Golang: 打印命令行参数
记得最早在学校机房学习 Java 时,照着书上的例子,写一个最简单 main 方法,当程序运行并在屏幕上打印出 hello world 时,内心竟有种莫名的激动,相信很多人都有这种经历吧. 不管学什么 ...
- 浅谈optparse 解析命令行参数库
使用的背景 在工作中我们经常要制定运行脚本的一些参数,因为有些东西是随着我么需求要改变的,所以在为们写程序的时候就一定不能把写死,这样我们就要设置参数 在python中我们可以通过sys 模板的arg ...
- linux 中解析命令行参数(getopt_long用法)
linux 中解析命令行参数(getopt_long用法) http://www.educity.cn/linux/518242.html 详细解析命令行的getopt_long()函数 http:/ ...
- GO语言标准库—命令行参数解析FLAG
flag包是Go语言标准库提供用来解析命令行参数的包,使得开发命令行工具更为简单 常用方法 1.flag.Usage 输出使用方法,如linux下ls -h的帮助输出 2.flag.Type(参数名, ...
- Google开源命令行参数解析库gflags
Google开源命令行参数解析库gflags http://blog.csdn.net/lming_08/article/details/25072899 CMDLINE的解析 http://blog ...
- boost之program_options库,解析命令行参数、读取配置文件
一.命令行解析 tprogram_options解析命令行参数示例代码: #include <iostream> using namespace std; #include <boo ...
- TensorFlow-谷歌深度学习库 命令行参数
程序的入口: tf.app.run tf.app.run( main=None, argv=None ) 运行程序,可以提供'main'函数以及函数参数列表.处理flag解析然后执行main函数. 什 ...
- golang命令行参数
os.Args获取命令行参数 os.Args是一个srting的切片,用来存储所有的命令行参数 package main import ( "fmt" "os" ...
随机推荐
- Java IO--字符流--BufferedReader和BufferedWriter
从昨天开始没事情干时,决定梳理梳理Java IO流,因为觉得太混乱这个东西,妈的,咋就这么多类型,想累死谁啊,这里并不是埋怨创造者,而是气自己看着看着老跑偏,实在看不进去,太多了,想睡觉,所以现在决定 ...
- 单台PC玩转NEUTRON(一:环境准备)
要开始从事云计算网络领域的技术研究.过去10年一直是从事传统网络相关的工作,新的事务在知识结构上还有一些差异,边学边写,作为个人总结,也共享给大家. 工欲善其事必先利其器,好的开发调测环境让人学习工作 ...
- 【机器学习基础】对 softmax 和 cross-entropy 求导
目录 符号定义 对 softmax 求导 对 cross-entropy 求导 对 softmax 和 cross-entropy 一起求导 References 在论文中看到对 softmax 和 ...
- asp.net core系列 57 IS4 使用混合流(OIDC+OAuth2.0)添加API访问
一.概述 在上篇中,探讨了交互式用户身份验证,使用的是OIDC协议. 在之前篇中对API访问使用的是OAuth2.0协议.这篇把这两个部分放在一起,OpenID Connect和OAuth 2.0组合 ...
- TensorFlow从1到2(三)数据预处理和卷积神经网络
数据集及预处理 从这个例子开始,相当比例的代码都来自于官方新版文档的示例.开始的几个还好,但随后的程序都将需要大量的算力支持.Google Colab是一个非常棒的云端实验室,提供含有TPU/GPU支 ...
- JAVA SPI(Service Provider Interface)原理、设计及源码解析(其一)
背景 团队内部轮流技术分享,其他人都是分享源码,我每次都是设计和架构,感觉自己太特立独行.这次我要合群点,分享点源码. 概念 Service Provider Interface:服务提供方接口.是一 ...
- 锁开销优化以及 CAS 简单说明
锁开销优化以及 CAS 简单说明 锁 互斥锁是用来保护一个临界区,即保护一个访问共用资源的程序片段,而这些共用资源又无法同时被多个线程访问的特性.当有线程进入临界区段时,其他线程或是进程必须等待. 在 ...
- 把时间留给重要的事——Markdown 模板功能上线
你是否遇到过因为同事在任务中过于放飞自我而感到头疼?或者经历过因为内容描写的不系统而导致关键信息被忽视? 现在,CODING Markdown 模板功能将帮助你解决这些困扰. 功能介绍 CODING ...
- 供应链管理为什么要上企业自主可控的免费开源ERP Odoo
引言 今天的很多企业,无论是制造业,还是商贸行业,如果说没有针对供应链管理的信息系统,那可能是真的冤枉他们了:采购.仓存.销售.存货核算这些模块,早早的买来,早早的用上了,但也早早的被下了结论:食之无 ...
- arcgis api 3.x for js 入门开发系列二十二地图模态层(附源码下载)
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...