golang命令行库cobra的使用

2023-10-30

简介

Cobra既是一个用来创建强大的现代CLI命令行的golang库,也是一个生成程序应用和命令行文件的程序。下面是Cobra使用的一个演示:

show

Cobra提供的功能

  • 简易的子命令行模式,如 app server, app fetch等等
  • 完全兼容posix命令行模式
  • 嵌套子命令subcommand
  • 支持全局,局部,串联flags
  • 使用Cobra很容易的生成应用程序和命令,使用cobra create appname和cobra add cmdname
  • 如果命令输入错误,将提供智能建议,如 app srver,将提示srver没有,是否是app server
  • 自动生成commands和flags的帮助信息
  • 自动生成详细的help信息,如app help
  • 自动识别-h,--help帮助flag
  • 自动生成应用程序在bash下命令自动完成功能
  • 自动生成应用程序的man手册
  • 命令行别名
  • 自定义help和usage信息
  • 可选的紧密集成的viper apps

如何使用

上面所有列出的功能我没有一一去使用,下面我来简单介绍一下如何使用Cobra,基本能够满足一般命令行程序的需求,如果需要更多功能,可以研究一下源码github

安装cobra

Cobra是非常容易使用的,使用go get来安装最新版本的库。当然这个库还是相对比较大的,可能需要安装它可能需要相当长的时间,这取决于你的速网。安装完成后,打开GOPATH目录,bin目录下应该有已经编译好的cobra.exe程序,当然你也可以使用源代码自己生成一个最新的cobra程序。

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

使用cobra生成应用程序

假设现在我们要开发一个基于CLIs的命令程序,名字为demo。首先打开CMD,切换到GOPATH的src目录下[^1],执行如下指令:
[^1]:cobra.exe只能在GOPATH目录下执行

src> ..\bin\cobra.exe init demo 
Your Cobra application is ready at
C:\Users\liubo5\Desktop\transcoding_tool\src\demo
Give it a try by going there and running `go run main.go`
Add commands to it by running `cobra add [cmdname]`

在src目录下会生成一个demo的文件夹,如下:

▾ demo
    ▾ cmd/
        root.go
    main.go

如果你的demo程序没有subcommands,那么cobra生成应用程序的操作就结束了。

如何实现没有子命令的CLIs程序

接下来就是可以继续demo的功能设计了。例如我在demo下面新建一个包,名称为imp。如下:

▾ demo
    ▾ cmd/
        root.go
    ▾ imp/
        imp.go
        imp_test.go
    main.go

imp.go文件的代码如下:

package imp

import(
    "fmt"
)

func Show(name string, age int) {
    fmt.Printf("My Name is %s, My age is %d\n", name, age)
}

demo程序成命令行接收两个参数name和age,然后打印出来。打开cobra自动生成的main.go文件查看:

// Copyright © 2016 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()
}

可以看出main函数执行cmd包,所以我们只需要在cmd包内调用imp包就能实现demo程序的需求。接着打开root.go文件查看:

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

    "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 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 != "" { // enable ability to specify config file via flag
        viper.SetConfigFile(cfgFile)
    }

    viper.SetConfigName(".demo") // name of config file (without extension)
    viper.AddConfigPath("$HOME")  // adding home directory as first search path
    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())
    }
}

从源代码来看cmd包进行了一些初始化操作并提供了Execute接口。十分简单,其中viper是cobra集成的配置文件读取的库,这里不需要使用,我们可以注释掉(不注释可能生成的应用程序很大约10M,这里没哟用到最好是注释掉)。cobra的所有命令都是通过cobra.Command这个结构体实现的。为了实现demo功能,显然我们需要修改RootCmd。修改后的代码如下:

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

    "github.com/spf13/cobra"
    //  "github.com/spf13/viper"
    "demo/imp"
)

//var cfgFile string
var name string
var age int

// RootCmd represents the base command when called without any subcommands
var RootCmd = &cobra.Command{
    Use:   "demo",
    Short: "A test demo",
    Long:  `Demo is a test appcation for print things`,
    // Uncomment the following line if your bare application
    // has an action associated with it:
    Run: func(cmd *cobra.Command, args []string) {
        if len(name) == 0 {
            cmd.Help()
            return
        }
        imp.Show(name, age)
    },
}

// Execute adds all child commands to the root command 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")
    RootCmd.Flags().StringVarP(&name, "name", "n", "", "person's name")
    RootCmd.Flags().IntVarP(&age, "age", "a", 0, "person's age")
}

// initConfig reads in config file and ENV variables if set.
//func initConfig() {
//  if cfgFile != "" { // enable ability to specify config file via flag
//      viper.SetConfigFile(cfgFile)
//  }

//  viper.SetConfigName(".demo") // name of config file (without extension)
//  viper.AddConfigPath("$HOME") // adding home directory as first search path
//  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())
//  }
//}

到此demo的功能已经实现了,我们编译运行一下看看实际效果:

>demo.exe
Demo is a test appcation for print things

Usage:
  demo [flags]

Flags:
  -a, --age int       person's age
  -h, --help          help for demo
  -n, --name string   person's name
>demo -n borey --age 26
My Name is borey, My age is 26

如何实现带有子命令的CLIs程序

在执行cobra.exe init demo之后,继续使用cobra为demo添加子命令test:

src\demo>..\..\bin\cobra add test
test created at C:\Users\liubo5\Desktop\transcoding_tool\src\demo\cmd\test.go

在src目录下demo的文件夹下生成了一个cmd\test.go文件,如下:

▾ demo
    ▾ cmd/
        root.go
        test.go
    main.go

接下来的操作就和上面修改root.go文件一样去配置test子命令。效果如下:

src\demo>demo
Demo is a test appcation for print things

Usage:
  demo [flags]
  demo [command]

Available Commands:
  test        A brief description of your command

Flags:
  -a, --age int       person's age
  -h, --help          help for demo
  -n, --name string   person's name

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

可以看出demo既支持直接使用标记flag,又能使用子命令

src\demo>demo 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]

调用test命令输出信息,这里没有对默认信息进行修改。

src\demo>demo tst
Error: unknown command "tst" for "demo"

Did you mean this?
        test

Run 'demo --help' for usage.
unknown command "tst" for "demo"

Did you mean this?
        test

这是错误命令提示功能

OVER

Cobra的使用就介绍到这里,更新细节可去github详细研究一下。这里只是一个简单的使用入门介绍,如果有错误之处,敬请指出,谢谢~

转载于:https://www.cnblogs.com/borey/p/5715641.html

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

golang命令行库cobra的使用 的相关文章

  • Linux 系列之常用命令记录整理

    Linux一些命令可以在开发或调试过程中起到很好的帮助作用 有些可以帮助了解或优化我们的程序 有些可以帮我们定位疑难问题 本篇博客将介绍工作中常用的linux命令 记得收藏 博客不定时更新 命令 功能说明 线上查询及帮助命令 2 个 man

随机推荐

  • 在Ubuntu 16.04上为树莓派(RaspBerry Pi 3)编译Android 7(Nougat)

    1 环境准备和介绍 本文章的测试环境如下 软件环境 VMware Workstation Pro Ubuntu 16 04 64 bit 虚拟机的内存配置6GB 4个CPU 硬件环境 RaspBerry Pi3 16GB SD卡 测试And
  • 1a电流用多粗的线

    1 由于敷铜板铜箔厚度有限 在需要流过较大电流的条状铜箔中 应考虑铜箔的载流量问题 仍以典型的0 03mm 厚度的为例 如果将铜箔作为宽为W mm 长度为L mm 的条状导线 其电阻为0 0005 L W 欧姆 另外 铜箔的载流量还与印刷电
  • 【python学习】python import

    Python import 的搜索路径 在当前目录下搜索该模块 在环境变量 PYTHONPATH 中指定的路径列表中依次搜索 在 Python 安装路径的 lib 库中搜索 如果在编程中模块和自己写的python文件不在同一个目录下 在文件
  • ADB

    更多硬件与系统属性 设备的更多硬件与系统属性可以通过如下命令查看 adb shell cat system build prop 这会输出很多信息 包括前面几个小节提到的 型号 和 Android 系统版本 等 输出里还包括一些其它有用的信
  • Hbuilderx APP真机运行 vivo iqoo neo5 开启adb调试

    使用UNIAPP开发APP 连接安卓手机vivo iqoo neo5 已开启USB调试模式 运行到手机模拟器仍提示 未检测到手机或者模拟器 请重试 解决办法 1 进入hbuilderx安装目录下plugins launcher tools
  • 飞桨框架2.0正式版重磅发布,一次端到端的“基础设施”革新

    在人工智能时代 深度学习框架下接芯片 上承各种应用 是 智能时代的操作系统 近期 我国首个自主研发 功能完备 开源开放的产业级深度学习框架飞桨发布了2 0正式版 实现了一次跨时代的升级 这次2 0版本的发布对于飞桨来说 可以说是一次 基础设
  • Unity3d 2021版本工程打开Visual Studio错误未找到这些文件,将无法加载的问题

    问题 最近是和Unity3d 2021版本杠上了啊 因为需要的一个功能必须用Unity3d 2021版本 所以带出来了这一系列的问题 这个问题是我在Unity编辑器上Open C Project之后VS会打不开工程 并提示 命令行中指定了以
  • [YOLO专题-15]:YOLO V5 - 如何从视频文件中生成训练样本的原始图片

    作者主页 文火冰糖的硅基工坊 文火冰糖 王文兵 的博客 文火冰糖的硅基工坊 CSDN博客 本文网址 https blog csdn net HiWangWenBing article details 122324063 前言 在构建自己的训
  • 里氏替换原则~

    里氏替换原则 Liskov Substitution Principle 是面向对象设计中的一个基本原则 它是由Barbara Liskov提出的 如果对于每一个类型为Apple的对象1 都有类型为fruit的对象2 使得以fruit定义的
  • [Git] 用一个分支的内容替换另一个分支,上传一个新分支到远程,重置分支到某一次提交

    新建一个dev分支 ray ray ubuntu git checkout b dev Switched to a new branch dev 将master分支的内容覆盖掉dev分支上 ray ray ubuntu git reset
  • cvc-complex-type.2.4.c: The matching wildcard is strict, but no declaration的解决

    导入了一个工程 编译什么的都还好 但是报了一个XML的错误 cvc complex type 2 4 c The matching wildcard is strict but no declaration can be found for
  • java selenium页面跳转页面跳转页面_4、selenium webdriver + java 进行元素定位时的页面跳转问题...

    在使用selenium Java对元素进行定位时经常遇见以下两种问题 问题一 在当前页面进行跳转时 提示 Unable to locate element 原因 driver在打开网页时 网页加载速度过慢 导致接下来的语句找不到元素 解决办
  • elementUI解决栅格布局一行放五个盒子放不下的问题

    1 问题图 2 解决办法 修改 lg span 24 5 这样在css中可以看到是 el col lg 24 5
  • 百度AI接口使用-图像增强篇

    地址 http ai baidu com 这里使用python接口 需要传入的是access token 返回是一个字典 其中image字段就是处理后的图片的base64编码 其中 access token需要去获取 如下 获取链接 htt
  • 结构体-初阶

    结构体是我们c语言初阶的最后一部分了 结束了结构体就要进入到c语言的进阶部分 1 结构体的声明 我们知道数组是一组相同类型的元素集合 而结构体可以是不同类型的元素集合 也可以保存相同类型 1 1 结构的声明 例如描述一个学生 typedef
  • 001 java为什么需要函数式编程

    一 概述 集合是我们java程序员每天都需要的工具 没有了集合 java程序员几乎不能干任何的事情 我们每天的工作也是在对集合进行不同的操作 尽管集合的功能已经足够强大 但是当我们面对复杂的业务问题的时候 利用原始的集合操作就会变得让人恶心
  • 十大PyTorch最常用的转换函数

    介绍 Pytorch是一个深度学习框架 广泛用于图像分类 分割 目标识别等各种任务 在这种情况下 我们必须处理各种类型的数据 很可能在大多数情况下 数据可能不是我们所需要的格式 PyTorch转换就是救星 torchvision trans
  • 恩施职业技术学院工程能力实训开班!青春逐梦,砥砺前行

    为深化校企合作 产教融合助力新工科建设 提升学生工程实践能力 电巢工程能力实训班按照不同岗位类别 匹配对应的企业岗位任职能力要求对学生开展分级培养 以产业需求为导向 培养创新型 应用型人才 6月13日上午 深圳电巢联合恩施职业技术学院 工程
  • SessionID漏洞

    漏洞原理 当用户第一次访问服务程序时 服务器端会给用户创建一个独立的会话Session 并且生成一个SessionID SessionID在响应浏览器的时候会被加载到cookie中 并保存到浏览器中 当用户再一次访问服务程序时 请求中会携带
  • golang命令行库cobra的使用

    简介 Cobra既是一个用来创建强大的现代CLI命令行的golang库 也是一个生成程序应用和命令行文件的程序 下面是Cobra使用的一个演示 Cobra提供的功能 简易的子命令行模式 如 app server app fetch等等 完全