Go语言命令行参数及cobra使用教程

news2024/12/22 4:28:26

Go语言命令行参数及cobra使用教程

  • 1.原生命令行参数
  • 2.使用CIL框架Cobra
    • 创建 rootCmd
    • 创建你的 main.go
    • 创建其他命令
    • 子命令
    • 返回和处理错误
  • 3.cobra使用标志
  • 4.Cobra位置参数和自定义参数
  • 5.Cobra PreRun和PostRun钩子

1.原生命令行参数

os 包以跨平台的方式,提供了一些与操作系统交互的函数和变量。程序的命令行参数可从 os 包的 Args 变量获取;os 包外部使用 os.Args 访问该变量

os.Args 变量是一个字符串(string)的 切片(slice),os.Args 的第一个元素:os.Args[0],是命令本身的名字;其它的元素则是程序启动时传给它的参数

func main() {
	var s, sep string
	for i := 1; i < len(os.Args); i++ {
		s += sep + os.Args[i]
		sep = " "
	}
	fmt.Println(s)
}

执行程序,会输出所有参数,以空格做分割:

go run hello.go 1 2.1 nma

在这里插入图片描述


2.使用CIL框架Cobra

cobra

Cobra 应用程序将遵循以下组织结构:

▾ appName/
  ▾ cmd/
      add.go
      your.go
      commands.go
      here.go
    main.go

创建 rootCmd

Cobra 不需要任何特殊的构造函数。只需创建命令即可

package cmd

import (
	"fmt"
	"os"

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

var (
	cfgFile     string // 配置文件路径
	userLicense string // 许可证类型

	rootCmd = &cobra.Command{
		// 应用名称
		Use: "cobra-cli",
		// 应用简短描述
		Short: "A generator for Cobra based Applications",
		// 应用详细描述
		Long: `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.`,
	}
)

// Execute 用于执行根命令 rootCmd
func Execute() error {
	return rootCmd.Execute()
}

func init() {
	// 在执行任何子命令之前调用 initConfig() 函数
	cobra.OnInitialize(initConfig)

	// 配置文件
	rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")
	// 作者信息
	rootCmd.PersistentFlags().StringP("author", "a", "YOUR NAME", "author name for copyright attribution")
	// 许可证信息
	rootCmd.PersistentFlags().StringVarP(&userLicense, "license", "l", "", "name of license for the project")
	// 使用Viper进行配置
	rootCmd.PersistentFlags().Bool("viper", true, "use Viper for configuration")
	// 将命令行标志绑定到 Viper 配置库中的相应参数
	err := viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
	if err != nil {
		return
	}
	err2 := viper.BindPFlag("useViper", rootCmd.PersistentFlags().Lookup("viper"))
	if err2 != nil {
		return
	}
	// 设置默认配置值
	viper.SetDefault("author", "NAME HERE <EMAIL ADDRESS>")
	viper.SetDefault("license", "apache")

	// 用于添加子命令
	rootCmd.AddCommand(addCmd)
	rootCmd.AddCommand(initCmd)
}

// 初始化应用程序的配置
func initConfig() {
	// 判断是否指定了配置文件路径,如果指定了,则将其设置为 Viper 配置文件
	if cfgFile != "" {
		viper.SetConfigFile(cfgFile)
	} else {
		// 如果没有指定配置文件路径,就根据用户的主目录动态生成配置文件路径
		home, err := os.UserHomeDir()
		cobra.CheckErr(err)
		viper.AddConfigPath(home)
		viper.SetConfigType("yaml")
		viper.SetConfigName(".cobra")
	}

	// 用于自动读取环境变量
	viper.AutomaticEnv()

	// 用于读取配置文件。如果成功读取,则输出使用的配置文件路径
	if err := viper.ReadInConfig(); err == nil {
		fmt.Println("Using config file:", viper.ConfigFileUsed())
	}
}

创建你的 main.go

main.go 文件通常非常裸露。它有一个目的:初始化 Cobra:

package go_test

import "go-test/cmd"

func main() {
	err := cmd.Execute()
	if err != nil {
		return
	}
}

创建其他命令

可以定义其他命令,并且通常每个命令都有自己的文件 在 cmd/ 目录中。

例如:如果要创建版本命令,则需要创建 cmd/version.go 和 使用以下内容填充它:

package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// 将 versionCmd 命令添加到根命令 rootCmd 中
func init() {
	rootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Print the version number of Hugo",
	Long:  `All software has versions. This is Hugo's`,
	// 用于定义命令被执行时的具体操作
	// 在本例中,当执行 version 命令时,会打印出 “Hugo Static Site Generator v0.9 – HEAD” 版本信息
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("Hugo Static Site Generator v0.9 -- HEAD")
	},
}

结合上面的代码,当用户输入 cobra-cli version 时,将会触发 versionCmd 命令的执行,打印出应用程序的版本信息

子命令

命令可能具有子命令,而子命令又可能具有其他子命令

请考虑以下目录结构:AddCommand

├── cmd
│   ├── root.go
│   └── sub1
│       ├── sub1.go
│       └── sub2
│           ├── leafA.go
│           ├── leafB.go
│           └── sub2.go
└── main.go

返回和处理错误

如果您希望向命令的调用方返回错误,可以使用RunE

package cmd

import (
  "fmt"

  "github.com/spf13/cobra"
)

func init() {
  rootCmd.AddCommand(tryCmd)
}

var tryCmd = &cobra.Command{
  Use:   "try",
  Short: "Try and possibly fail at something",
  RunE: func(cmd *cobra.Command, args []string) error {
    if err := someFunc(); err != nil {
	return err
    }
    return nil
  },
}

3.cobra使用标志

标志提供修饰符来控制操作命令的运行方式

1、持久性标志

标志可以是“持久性的”,这意味着此标志将可用于它所分配的命令以及该命令下的每个命令。为全局标志,将标志指定为根上的持久标志

持久性标记的定义通常包括全局性的配置参数,例如日志级别、配置文件路径、全局选项等

rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")

2、本地标志

在本地分配标志,该标志仅适用于该特定命令

本地标记通常用于定义特定命令所需的选项和参数,例如某个命令的特定配置选项

localCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")

3、使用 Config 绑定标志

可以使用 viper 绑定您的标志:

var author string

func init() {
  rootCmd.PersistentFlags().StringVar(&author, "author", "YOUR NAME", "Author name for copyright attribution")
  viper.BindPFlag("author", rootCmd.PersistentFlags().Lookup("author"))
}

使用 Viper 绑定命令行标志可使配置管理更加一致、灵活和可组合。然而,具体是否需要绑定命令行标志取决于你的应用程序需求和偏好,如果你认为手动处理命令行标志更适合你,也可以不使用 Viper 进行绑定

4、参数必须

默认情况下,标志是可选的,如果想设置某个参数是必要的,可以进行设置:

rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkFlagRequired("region")

或者,对于持久性标志:

rootCmd.PersistentFlags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkPersistentFlagRequired("region")

5、标记Groups

如果您有不同的标志必须一起提供(例如,如果他们提供标志,他们也必须提供标志),也可以强制进行设定:

rootCmd.Flags().StringVarP(&u, "username", "u", "", "Username (required if password is set)")
rootCmd.Flags().StringVarP(&pw, "password", "p", "", "Password (required if username is set)")
rootCmd.MarkFlagsRequiredTogether("username", "password")

还可以设置不同标记的互斥(也就是不能同时出现):

rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON")
rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML")
rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")

如果要要求组中至少有一个标志存在,也可以指定:

rootCmd.Flags().BoolVar(&ofJson, "json", false, "Output in JSON")
rootCmd.Flags().BoolVar(&ofYaml, "yaml", false, "Output in YAML")
rootCmd.MarkFlagsOneRequired("json", "yaml")
rootCmd.MarkFlagsMutuallyExclusive("json", "yaml")

4.Cobra位置参数和自定义参数

可以指定位置参数的验证:

内置了以下验证器:Args Command

参数数量:

  • NoArgs- 如果有任何位置参数,则报告错误。
  • ArbitraryArgs- 接受任意数量的参数。
  • MinimumNArgs(int)- 如果提供的位置参数少于 N 个,则报告错误。
  • MaximumNArgs(int)- 如果提供了超过 N 个位置参数,则报告错误。
  • ExactArgs(int)- 如果位置参数不完全是 N 个,则报告错误。
  • RangeArgs(min, max)- 如果参数数不在min和max之间,则报告错误

论据内容:

  • OnlyValidArgs- 如果字段中未指定任何位置参数,则报告错误

此外,还可以将现有检查与任意其他检查相结合,例如:

var cmd = &cobra.Command{
  Short: "hello",
  Args: cobra.MatchAll(cobra.ExactArgs(2), cobra.OnlyValidArgs),
  Run: func(cmd *cobra.Command, args []string) {
    fmt.Println("Hello, World!")
  },
}

可以设置任何满足的自定义验证器,例如:

var cmd = &cobra.Command{
  Short: "hello",
  Args: func(cmd *cobra.Command, args []string) error {
    if err := cobra.MinimumNArgs(1)(cmd, args); err != nil {
        return err
    }
    // 运行自定义验证逻辑
    if myapp.IsValidColor(args[0]) {
      return nil
    }
    return fmt.Errorf("invalid color specified: %s", args[0])
  },
  Run: func(cmd *cobra.Command, args []string) {
    fmt.Println("Hello, World!")
  },
}

5.Cobra PreRun和PostRun钩子

在 Cobra 库中,命令的执行过程被分为多个阶段,并且 Cobra 提供了一些Hooks来允许开发者在这些阶段插入自定义的行为

1、PersistentPreRun

在执行任何命令之前调用 PersistentPreRun。可以使用这个钩子来进行全局的初始化操作或者检查全局的配置参数

2、PreRun

在执行该命令之前调用 PreRun。可以使用这个钩子来执行一些与特定命令相关的操作或配置检查

3、Run

当命令被执行时,会调用 Run 函数来执行实际的命令操作

4、PostRun

在执行完该命令之后调用 PostRun。可以使用这个钩子来执行一些与特定命令相关的清理工作或后处理操作

5、PersistentPostRun

在执行完任何命令之后调用 PersistentPostRun。可以使用这个钩子来进行全局的清理工作或输出全局概要信息

例如:

package main

import (
  "fmt"

  "github.com/spf13/cobra"
)

func main() {

  var rootCmd = &cobra.Command{
    Use:   "root [sub]",
    Short: "My root command",
    PersistentPreRun: func(cmd *cobra.Command, args []string) {
      fmt.Printf("Inside rootCmd PersistentPreRun with args: %v\n", args)
    },
    PreRun: func(cmd *cobra.Command, args []string) {
      fmt.Printf("Inside rootCmd PreRun with args: %v\n", args)
    },
    Run: func(cmd *cobra.Command, args []string) {
      fmt.Printf("Inside rootCmd Run with args: %v\n", args)
    },
    PostRun: func(cmd *cobra.Command, args []string) {
      fmt.Printf("Inside rootCmd PostRun with args: %v\n", args)
    },
    PersistentPostRun: func(cmd *cobra.Command, args []string) {
      fmt.Printf("Inside rootCmd PersistentPostRun with args: %v\n", args)
    },
  }

  var subCmd = &cobra.Command{
    Use:   "sub [no options!]",
    Short: "My subcommand",
    PreRun: func(cmd *cobra.Command, args []string) {
      fmt.Printf("Inside subCmd PreRun with args: %v\n", args)
    },
    Run: func(cmd *cobra.Command, args []string) {
      fmt.Printf("Inside subCmd Run with args: %v\n", args)
    },
    PostRun: func(cmd *cobra.Command, args []string) {
      fmt.Printf("Inside subCmd PostRun with args: %v\n", args)
    },
    PersistentPostRun: func(cmd *cobra.Command, args []string) {
      fmt.Printf("Inside subCmd PersistentPostRun with args: %v\n", args)
    },
  }

  rootCmd.AddCommand(subCmd)

  rootCmd.SetArgs([]string{""})
  rootCmd.Execute()
  fmt.Println()
  rootCmd.SetArgs([]string{"sub", "arg1", "arg2"})
  rootCmd.Execute()
}

输出:

Inside rootCmd PersistentPreRun with args: []
Inside rootCmd PreRun with args: []
Inside rootCmd Run with args: []
Inside rootCmd PostRun with args: []
Inside rootCmd PersistentPostRun with args: []

Inside rootCmd PersistentPreRun with args: [arg1 arg2]
Inside subCmd PreRun with args: [arg1 arg2]
Inside subCmd Run with args: [arg1 arg2]
Inside subCmd PostRun with args: [arg1 arg2]
Inside subCmd PersistentPostRun with args: [arg1 arg2]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1351109.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

机器学习-基于attention机制来实现对Image Caption图像描述实验

机器学习-基于attention机制来实现对Image Caption图像描述实验 实验目的 基于attention机制来实现对Image Caption图像描述 实验内容 1.了解一下RNN的Encoder-Decoder结构 在最原始的RNN结构中&#xff0c;输入序列和输出序列必须是严格等长的。但在机器翻译等任务中&…

你真的会用Pycharm?这本耗时2年编写的《Pycharm中文指南》,解决你的困惑!

很多读者应该非常了解 JetBrains 开发的 PyCharm 了&#xff0c;它差不多是 Python 最常用的 IDE之一。PyCharm的优势在于可以为我们节省大量时间、管理代码&#xff0c;并完成大量其他任务&#xff0c;如 debug 和可视化等。 需要最新专业版PyCharm永久使用权限的扫码获取 那…

华为高级Java面试真题

今年IT寒冬&#xff0c;大厂都裁员或者准备裁员&#xff0c;作为开猿节流主要目标之一&#xff0c;我们更应该时刻保持竞争力。为了抱团取暖&#xff0c;林老师开通了《知识星球》&#xff0c;并邀请我阿里、快手、腾讯等的朋友加入&#xff0c;分享八股文、项目经验、管理经验…

解决jenkins的Exec command命令不生效,或者执行停不下来的问题

Jenkins构建完后将war包通过 Publish Over SSH 的插件发布到服务器上&#xff0c;在服务器上执行脚本时&#xff0c;脚本中的 nohup 命令无法执行&#xff0c;并不生效&#xff0c;我配置的Exec command命令是后台启动一个war包&#xff0c;并输出日志文件。 nohup java -jar /…

第二十三章 反射

第二十三章 反射 1.反射机制问题2.反射快速入门3.发射原理图4.反射相关类5.发射调用优化6.Class类分析7.Class常用方法8.获取Class对象的6种方式9.哪些类型有Class对象10.动态和静态加载11.类加载流程图12.类加载五个阶段&#xff08;1&#xff09;13.类加载五个阶段&#xff0…

OpenGL FXAA抗锯齿算法(Qt,Consloe版本)

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 之前已经提供了使用VCG读取Mesh的方式,接下来就需要针对读取的网格数据进行一些渲染操作了。在绘制Mesh数据时总会遇到图形的抗锯齿问题,OpenGL本身已经为我们提供了一种MSAA技术,但该技术对于一些实时渲染性能有…

【代数学作业1完整版-python实现GNFS一般数域筛】构造特定的整系数不可约多项式:涉及素数、模运算和优化问题

代数学作业1-完整版&#xff1a;python实现GNFS一般数域筛 写在最前面背景在GNFS算法中选择互质多项式时&#xff0c;需要考虑哪些关键因素&#xff0c;它们对算法的整体运行时间有何影响? 练习1题目题目分析Kleinjung方法简介通用数域筛法&#xff08;GNFS&#xff09;中的多…

论文阅读--EFFICIENT OFFLINE POLICY OPTIMIZATION WITH A LEARNED MODEL

作者&#xff1a;Zichen Liu, Siyi Li, Wee Sun Lee, Shuicheng YAN, Zhongwen Xu 论文链接&#xff1a;Efficient Offline Policy Optimization with a Learned Model | OpenReview 发表时间&#xff1a; ICLR 2023年1月21日 代码链接&#xff1a;https://github.com/s…

Nginx 代理静态资源,解决跨域问题

&#x1f602; 背景&#xff1a;移动端 H5 项目&#xff0c;依赖了一个外部的 JS 文件。访问时&#xff0c;出现跨域&#xff0c;导致请求被 block。 当前域名&#xff1a;https://tmcopss.test.com要访问的 JS 文件&#xff1a;https://tm.test.com/public/scripts/y-jssdk.j…

下载与安装Python解释器

文章目录 一. 下载Python解释器二. 安装Python解释器总结 一. 下载Python解释器 下载地址&#xff1a;https://www.python.org/downloads/release/python-372/ 查找目标文件&#xff1a;Windows x86-64 executable installer – 单击即可下载。 这里贴出我下载好的网盘链接…

从0到1实战,快速搭建SpringBoot工程

目录 一、前言 二、准备工作 2.1 安装JDK 2.2 安装Maven 2.3 下载IDEA 三、从0到1搭建 3.1 创建SpringBoot工程 3.2 运行SpringBoot工程 四、总结 一、前言 SpringBoot是一个在Spring框架基础上构建的开源框架&#xff0c;不仅继承了Spring框架原有的优秀特性&#x…

软件测试/测试开发丨Python 模块与包

python 模块与包 python 模块 项目目录结构 组成 package包module模块function方法 模块定义 定义 包含python定义和语句的文件.py文件作为脚本运行 导入模块 import 模块名from <模块名> import <方法 | 变量 | 类>from <模块名> import * 注意&a…

JAVA反序列化之URLDNS链分析

简单介绍下urldns链 在此之前最好有如下知识&#xff0c;请自行bing or google学习。 什么是序列化 反序列化 &#xff1f;特点&#xff01; java对象反射调用&#xff1f; hashmap在java中是一种怎样的数据类型&#xff1f; dns解析记录有那…

canvas绘制网格线示例

查看专栏目录 canvas示例教程100专栏&#xff0c;提供canvas的基础知识&#xff0c;高级动画&#xff0c;相关应用扩展等信息。canvas作为html的一部分&#xff0c;是图像图标地图可视化的一个重要的基础&#xff0c;学好了canvas&#xff0c;在其他的一些应用上将会起到非常重…

ArkTS - @Builder自定义构建函数

这个Builder作用就是可以把组件样式抽离出来&#xff0c;写成公共组件&#xff0c;下边记录下全局自定义构建函数用法及注意的地方。 官方文档&#xff1a;开发者可以将重复使用的UI元素抽象成一个方法&#xff0c;在build方法里调用。 一、用法 下边代码&#xff0c;我在Co…

LangChain(0.0.340)官方文档十一:Agents之Agent Types

LangChain官网、LangChain官方文档 、langchain Github、langchain API文档、llm-universe《Agent Types》、《Examples using AgentType》 文章目录 一、快速入门1.1 概念1.2 基本示例1.2.1 配置LangSmith1.2.2 使用LCEL语法创建Agents1.2.3 使用自定义runtime执行1.2.4 使用A…

uniapp中用户登录数据的存储方法探究

Hello大家好&#xff01;我是咕噜铁蛋&#xff01;作为一个博主&#xff0c;我们经常需要在应用程序中实现用户登录功能&#xff0c;并且需要将用户的登录数据进行存储&#xff0c;以便在多次使用应用程序时能够方便地获取用户信息。铁蛋通过科技手段帮大家收集整理了些知识&am…

八大算法排序@选择排序

目录 选择排序概念算法思想示例步骤1步骤2步骤...n最后一步 代码实现时间复杂度空间复杂度特性总结 选择排序 概念 选择排序&#xff08;Selection Sort&#xff09;是一种简单直观的排序算法。基本思想是在未排序的序列中找到最小&#xff08;或最大&#xff09;元素&#xf…

BIO和NIO编程(待完善)

目录 IO模型 BIO NIO 常见问题 IO模型 Java共支持3种网络编程IO模式&#xff1a;BIO&#xff0c;NIO&#xff0c;AIO BIO 同步阻塞模型&#xff0c;一个客户端连接对应一个处理线程 代码示例&#xff1a; Server端&#xff1a; public class BioServer {private static …

K8S集群部署MySql

挂载MySQL数据卷 在k8s集群中挂载MySQL数据卷 需要安装一个NFS。 在主节点安装NFS yum install -y nfs-utils rpcbind 在主节点创建目录 mkdir -p /nfs chmod 777 /nfs 更改归属组与用户 chown -R nfsnobody:nfsnobody /nfs 配置共享目录 echo "/nfs *(insecure,rw,s…