我的编程空间,编程开发者的网络收藏夹
学习永远不晚

怎么在Golang中使用Cobra创建CLI应用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

怎么在Golang中使用Cobra创建CLI应用

本篇内容主要讲解“怎么在Golang中使用Cobra创建CLI应用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么在Golang中使用Cobra创建CLI应用”吧!

对于开发人员来说平时可能就需要使用到很多 CLI 工具,比如 npm、node、go、python、docker、kubectl 等等,因为这些工具非常小巧、没有依赖性、非常适合系统管理或者一些自动化任务等等。

我们这里选择使用 Golang 里面非常有名的Cobra库来进行 CLI 工具的开发。Cobra 是一个功能强大的现代化 CLI 应用程序库,有很多知名的 Go 项目使用 Cobra 进行构建,比如:Kubernetes、Docker、Hugo 等等

概念

Cobra 是构建在命令、参数和标识符之上的:

  • Commands表示执行动作

  • Args就是执行参数

  • Flags是这些动作的标识符

基本的执行命令如下所示:

$ APPNAME Command Args --Flags# 或者$ APPNAME Command --Flags Args

比如我们平时使用的一些命令行工具:

git clone URL -barego get -u URLnpm install package –savekubectl get pods -n kube-system -l app=cobra

示例

下面我们来看下 Cobra 的使用,这里我们使用的 go1.13.3 版本,使用 Go Modules 来进行包管理,如果对这部分知识点不熟悉的,可以查看前面我们的文章Go Modules 基本使用(视频)了解。

新建一个名为my-calc的目录作为项目目录,然后初始化 modules:

$ mkdir my-calc && cd my-calc# 如果 go modules 默认没有开启,需要执行 export GO111MODULE=on 开启$ go mod init my-calcgo: creating new go.mod: module my-calc

初始化完成后可以看到项目根目录下面多了一个go.mod的文件,现在我们还没有安装cobra库,执行下面的命令进行安装:

# 强烈推荐配置该环境变量$ export GOPROXY=https://goproxy.cn$ go get -u github.com/spf13/cobra/cobra

安装成功后,现在我们可以使用cobra init命令来初始化 CLI 应用的脚手架:

$ cobra init --pkg-name my-calcYour Cobra applicaton is ready at/Users/ych/devs/workspace/youdianzhishi/course/my-calc

需要注意的是新版本的 cobra 库需要提供一个--pkg-name参数来进行初始化,也就是指定上面我们初始化的模块名称即可。上面的 init 命令就会创建出一个最基本的 CLI 应用项目:

$ tree ..├── LICENSE├── cmd│   └── root.go├── go.mod├── go.sum└── main.go1 directory, 5 files

其中main.go是 CLI 应用的入口,在main.go里面调用好了cmd/root.go下面的Execute函数:

// main.gopackage mainimport "my-calc/cmd"func main() {cmd.Execute()}

然后我们再来看下cmd/root.go文件。

rootCmd

root(根)命令是 CLI 工具的最基本的命令,比如对于我们前面使用的go get URL,其中go就是 root 命令,而get就是go这个根命令的子命令,而在root.go中就直接使用了 cobra 命令来初始化rootCmd结构,CLI 中的其他所有命令都将是rootCmd这个根命令的子命令了。

这里我们将cmd/root.go里面的rootCmd变量内部的注释去掉,并在Run函数里面加上一句fmt.Println("Hello Cobra CLI")

var rootCmd = &cobra.Command{Use:   "my-calc",Short: "A brief description of your application",Long: `A longer description that spans multiple lines and likely containsexamples 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 filesto quickly create a Cobra application.`,Run: func(cmd *cobra.Command, args []string) {        fmt.Println("Hello Cobra CLI")    },}

这个时候我们在项目根目录下面执行如下命令进行构建:

$ go build -o my-calc

该命令会在项目根目录下生成一个名为my-calc的二进制文件,直接执行这个二进制文件可以看到如下所示的输出信息:

$ ./my-calc
Hello Cobra CLI

init

我们知道init函数是 Golang 中初始化包的时候第一个调用的函数。在cmd/root.go中我们可以看到init函数中调用了cobra.OnInitialize(initConfig),也就是每当执行或者调用命令的时候,它都会先执行init函数中的所有函数,然后再执行execute方法。该初始化可用于加载配置文件或用于构造函数等等,这完全依赖于我们应用的实际情况。

在初始化函数里面cobra.OnInitialize(initConfig)调用了initConfig这个函数,所有,当rootCmd的执行方法RUN: func运行的时候,rootCmd根命令就会首先运行initConfig函数,当所有的初始化函数执行完成后,才会执行rootCmdRUN: func执行函数。

我们可以在initConfig函数里面添加一些 Debug 信息:

func initConfig() {    fmt.Println("I'm inside initConfig function in cmd/root.go")    ...}

然后同样重新构建一次再执行:

$ go build -o my-calc$ ./my-calcI'm inside initConfig function in cmd/root.goHello Cobra CLI

可以看到是首先运行的是initConfig函数里面的信息,然后才是真正的执行函数里面的内容。

为了搞清楚整个 CLI 执行的流程,我们在main.go里面也添加一些 Debug 信息:

// cmd/root.gofunc init() {    fmt.Println("I'm inside init function in cmd/root.go")    cobra.OnInitialize(initConfig)    ...}func initConfig() {    fmt.Println("I'm inside initConfig function in cmd/root.go")    ...}// main.gofunc main() {     fmt.Println("I'm inside main function in main.go")     cmd.Execute()}

然后同样重新构建一次再执行:

$ go build -o my-calc$ ./my-calcI'm inside init function in cmd/root.goI'm inside main function in main.goI'm inside initConfig function in cmd/root.goHello Cobra CLI

根据上面的日志信息我们就可以了解到 CLI 命令的流程了。

init函数最后处理的就是flags了,Flags就类似于命令的标识符,我们可以把他们看成是某种条件操作,在 Cobra 中提供了两种类型的标识符:Persistent FlagsLocal Flags

  • Persistent Flags: 该标志可用于为其分配的命令以及该命令的所有子命令。

  • Local Flags: 该标志只能用于分配给它的命令。

initConfig

该函数主要用于在 home 目录下面设置一个名为.my-calc的配置文件,如果该文件存在则会使用这个配置文件。

// cmd/root.go// initConfig 读取配置文件和环境变量func initConfig() {if cfgFile != "" {        // 使用 flag 标志中传递的配置文件viper.SetConfigFile(cfgFile)} else {// 获取 Home 目录home, err := homedir.Dir()if err != nil {fmt.Println(err)os.Exit(1)}// 在 Home 目录下面查找名为 ".my-calc" 的配置文件viper.AddConfigPath(home)viper.SetConfigName(".my-calc")}    // 读取匹配的环境变量viper.AutomaticEnv()// 如果有配置文件,则读取它if err := viper.ReadInConfig(); err == nil {fmt.Println("Using config file:", viper.ConfigFileUsed())}}

viper是一个非常优秀的用于解决配置文件的 Golang 库,它可以从 JSON、TOML、YAML、HCL、envfile 以及 Java properties 配置文件中读取信息,功能非常强大,而且不仅仅是读取配置这么简单,了解更多相关信息可以查看 Git 仓库相关介绍:https://github.com/spf13/viper。

现在我们可以去掉前面我们添加的一些打印语句,我们已经创建了一个my-calc命令作为rootCmd命令,执行该根命令会打印Hello Cobra CLI信息,接下来为我们的 CLI 应用添加一些其他的命令。

添加数据

在项目根目录下面创建一个名为add的命令,Cobra添加一个新的命令的方式为:cobra add <commandName>,所以我们这里直接这样执行:

$ cobra add addadd created at /Users/ych/devs/workspace/youdianzhishi/course/my-calc$ tree ..├── LICENSE├── cmd│   ├── add.go│   └── root.go├── go.mod├── go.sum├── main.go└── my-calc1 directory, 7 files

现在我们可以看到cmd/root.go文件中新增了一个add.go的文件,我们仔细观察可以发现该文件和cmd/root.go比较类似。首先是声明了一个名为addCmd的结构体变量,类型为*cobra.Command指针类型,*cobra.Command有一个RUN函数,带有*cobra.Command指针和一个字符串切片参数。

然后在init函数中进行初始化,初始化后,将其添加到rootCmd根命令中rootCmd.AddCommand(addCmd),所以我们可以把addCmd看成是rootCmd的子命令。

同样现在重新构建应用再执行:

$ go build -o my-calc$ ./my-calcHello Cobra CLI$ ./my-calc addadd called

可以看到add命令可以正常运行了,接下来我们来让改命令支持添加一些数字,我们知道在RUN函数中是用户字符串 slice 来作为参数的,所以要支持添加数字,我们首先需要将字符串转换为 int 类型,返回返回计算结果。在cmd/add.go文件中添加一个名为intAdd的函数,定义如下所示:

// cmd/add.gofunc intAdd(args []string) {var sum int// 循环 args 参数,循环的第一个值为 args 的索引,这里我们不需要,所以用 _ 忽略掉for _, ival := range args {// 将 string 转换成 int 类型temp, err := strconv.Atoi(ival)if err != nil {panic(err)}sum = sum + temp}fmt.Printf("Addition of numbers %s is %d\n", args, sum)}

然后在addCmd变量中,更新RUN函数,移除默认的打印信息,调用上面声明的addInt函数:

// addCmdRun: func(cmd *cobra.Command, args []string) {    intAdd(args)},

然后重新构建应用执行如下所示的命令:

$ go build -o my-calc$ ./my-calcHello Cobra CLI# 注意参数之间的空格$ ./my-calc add 1 2 3Addition of numbers [1 2 3] is 6

由于RUN函数中的args参数是一个字符串切片,所以我们可以传递任意数量的参数,但是确有一个缺陷,就是只能进行整数计算,不能计算小数,比如我们执行如下的计算就会直接 panic 了:

$ ./my-calc add 1 2 3.5panic: strconv.Atoi: parsing "3.5": invalid syntaxgoroutine 1 [running]:my-calc/cmd.intAdd(0xc0000a5890, 0x3, 0x3)......

因为在intAdd函数里面,我们只是将字符串转换成了 int,而不是 float32/64 类型,所以我们可以为addCmd命令添加一个flag标识符,通过该标识符来帮助 CLI 确定它是 int 计算还是 float 计算。

cmd/add.go文件的init函数内部,我们创建一个 Bool 类型的本地标识符,命名成float,简写成f,默认值为 false。这个默认值是非常重要的,意思就是即使没有在命令行中调用 flag 标识符,该标识符的值就将为 false。

// cmd/add.gofunc init() {rootCmd.AddCommand(addCmd)addCmd.Flags().BoolP("float", "f", false, "Add Floating Numbers")}

然后创建一个floatAdd的函数:

func floatAdd(args []string) {var sum float64for _, fval := range args {// 将字符串转换成 float64 类型temp, err := strconv.ParseFloat(fval, 64)if err != nil {panic(err)}sum = sum + temp}fmt.Printf("Sum of floating numbers %s is %f\n", args, sum)}

该函数和上面的intAdd函数几乎是相同的,除了是将字符串转换成 float64 类型。然后在addCmdRUN函数中,我们根据传入的标识符来判断到底应该是调用intAdd还是floatAdd,如果传递了--float或者-f标志,就将会调用floatAdd函数。

// cmd/add.go// addCmdRun: func(cmd *cobra.Command, args []string) {    // 获取 float 标识符的值,默认为 false    fstatus, _ := cmd.Flags().GetBool("float")    if fstatus { // 如果为 true,则调用 floatAdd 函数        floatAdd(args)    } else {        intAdd(args)    }},

现在重新编译构建 CLI 应用,按照如下方式执行:

$ go build -o my-calc$ ./my-calc add 1 2 3Addition of numbers [1 2 3] is 6$ ./my-calc add 1 2 3.5 -fSum of floating numbers [1 2 3.5] is 6.500000$./my-calc add 1 2 3.5 --floatSum of floating numbers [1 2 3.5] is 6.500000

然后接下来我们在给addCmd添加一些子命令来扩展它。

添加偶数

同样在项目根目录下执行如下命令添加一个名为even的命令:

$ cobra add eveneven created at /Users/ych/devs/workspace/youdianzhishi/course/my-calc

和上面一样会在root目录下面新增一个名为even.go的文件,修改该文件中的init函数,将rootCmd修改为addCmd,因为我们是为addCmd添加子命令:

// cmd/even.gofunc init() {addCmd.AddCommand(evenCmd)}

然后更新evenCmd结构体参数的RUN函数:

// cmd/even.goRun: func(cmd *cobra.Command, args []string) {    var evenSum int    for _, ival := range args {        temp, _ := strconv.Atoi(ival)        if temp%2 == 0 {            evenSum = evenSum + temp        }    }    fmt.Printf("The even addition of %s is %d\n", args, evenSum)},

首先将字符串转换成整数,然后判断如果是偶数才进行累加。然后重新编译构建应用:

$ go build -o my-calc$ ./my-calc add even 1 2 3 4 5 6The even addition of [1 2 3 4 5 6] is 12

my-calc是我们的根命令,addrootCmd的子命令,even优势addCmd的子命令,所以按照上面的方式调用。可以用同样的方式再去添加一个奇数相加的子命令。

到此,相信大家对“怎么在Golang中使用Cobra创建CLI应用”有了更深的了解,不妨来实际操作一番吧!这里是编程网网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

怎么在Golang中使用Cobra创建CLI应用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

怎么在Golang中使用Cobra创建CLI应用

本篇内容主要讲解“怎么在Golang中使用Cobra创建CLI应用”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么在Golang中使用Cobra创建CLI应用”吧!对于开发人员来说平时可能就需
2023-06-22

如何在golang中使用cobra库

如何在golang中使用cobra库?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。cobra 是 go 语言的一个库,可以用于编写命令行工具。通常我们可以看到
2023-06-15

使用Vue怎么创建一个vue-cli脚手架程序

使用Vue怎么创建一个vue-cli脚手架程序?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。1. Vue--第一个vue-cli程序Vue的开发都是要基于Nod
2023-06-15

怎么在python中使用threading创建线程

本篇文章为大家展示了怎么在python中使用threading创建线程,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。Python主要用来做什么Python主要应用于:1、Web开发;2、数据科学研究
2023-06-14

怎么在python中使用pipenv创建环境

怎么在python中使用pipenv创建环境?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。python是什么意思Python是一种跨平台的、具有解释性、编译性、互动性和面向
2023-06-14

怎么在python中使用tempfile创建文件

本篇文章给大家分享的是有关怎么在python中使用tempfile创建文件,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。python是什么意思Python是一种跨平台的、具有解
2023-06-14

怎么在linux中使用useradd命令创建用户

这篇文章将为大家详细讲解有关怎么在linux中使用useradd命令创建用户,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。一,adduser与useradd命令二者的关系 代码示例:[roo
2023-06-09

怎么在Goland中使用Go Modules创建项目

这篇文章将为大家详细讲解有关怎么在Goland中使用Go Modules创建项目,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。创建项目Location:新项目文件夹GOROOT:go 安装根
2023-06-14

怎么在Python中使用numpy创建空数组

怎么在Python中使用numpy创建空数组?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。一、问题描述:有一个shape为(308, 2)的二维数组,以及单独的
2023-06-15

使用Django怎么创建一个应用程序

使用Django怎么创建一个应用程序?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。1、要在Django项目中创建基本应用,您需要转到包含manage.py的目录,然后从此处
2023-06-14

怎么使用SAP WebIDE创建开发Java应用

这篇文章主要讲解了“怎么使用SAP WebIDE创建开发Java应用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“怎么使用SAP WebIDE创建开发Java应用”吧!打开SAP WebID
2023-06-04

Ubuntu怎么使用SQLServer创建Go应用程序

本文小编为大家详细介绍“Ubuntu怎么使用SQLServer创建Go应用程序”,内容详细,步骤清晰,细节处理妥当,希望这篇“Ubuntu怎么使用SQLServer创建Go应用程序”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来
2023-07-06

Ring怎么在Golang中使用

今天就跟大家聊聊有关Ring怎么在Golang中使用,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。golang的优点golang是一种编译语言,可以将代码编译为机器代码,编译后的二进
2023-06-14

bytes.Buffer怎么在golang中使用

bytes.Buffer怎么在golang中使用?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。go适合做什么go是golang的简称,而golang可以做服务器
2023-06-14

如何在使用golang创建的wasm中实现多线程?

积累知识,胜过积蓄金银!毕竟在Golang开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《如何在使用golang创建的wasm中实现多线程?》,就带大家讲解一下知识点
如何在使用golang创建的wasm中实现多线程?
2024-04-05

怎么在PHP中使用array_combine()函数创建数组

本篇文章为大家展示了怎么在PHP中使用array_combine()函数创建数组,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。php有什么特点1、执行速度快。2、具有很好的开放性和可扩展性。3、PH
2023-06-14

Kubernetes中怎么创建一个Nginx应用

本篇文章给大家分享的是有关Kubernetes中怎么创建一个Nginx应用,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。使用命令行kubectl run --image=ngi
2023-06-06

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录