go 命令行框架cobra

news2024/11/14 22:07:15

go 命令行框架cobra

go 拉取依赖包go get github.com/spf13/cobra

认识spf13/cobra-cli. cobra 命令行框架在golang中的地位也算得上是大明星级别。像k8s,docker都有使用这个框架构建自己命令行这块的功能.

最最最简单的开始----使用命令行工具cobra-cli来初始化你的demo

cobra-cli init 初始化你的demo.后面可以加目录名,不加就是当前目录下创建一个main.go 和cmd目录(如果这时你main.go里写了东西,先备份再初始化)。cmd目录cobra-cli是用来储存子命令的地方,后面我们手动写的时候这个就不重要了

cobra-cli add options 添加一个子命令。例如你的demo名叫demo,你需要实现一个demo put xxxx的功能。cobra-cli add put

cobra-cli add options -p parent_optionCmd 子命令添加子命令。例如给上面的put加一个子命令为single cobra-cli add single -p putCmd 这里p参数为指定该命令的父命令,需要加后缀Cmd,因为-p参数实际是代码中的参数名,而cobra-cli自动创建命令时参数名为格式为xxxxCmd

编译demo. 运行demo 带-h查看cobra-cli生成的效果

认识cobra-cli框架下的命令行命令构造

每一个命令可以说是独立的,但是整个程序得有一个根命令rootCmd,这个rootCmd和其它命令性质都是一样的(都可以具备独立的flagset,usage)。只不过它的位置是“树根”而已
请添加图片描述

参数

  • 兼容golang 标准库flag.FlagSet
  • 能够设置必备参数(必填的参数)
//以putCmd为例
/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cmd

import (
	"fmt"
	"log"

	"github.com/spf13/cobra"
)

// putCmd represents the put command
var putCmd = &cobra.Command{
	Use:   "put",//子命令的具体名字
	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("put called")
	},
}

func init() {
	rootCmd.AddCommand(putCmd)//将putCmd添加到rootCmd的分支上去。成为rootCmd的子命令
	//为put命令添加参数,结尾有P的为带缩写的参数。添加的时候看清楚你添加的命令是哪一个,别搞混了搞到rootCmd上去了
	fs := flag.NewFlagSet("put", flag.ExitOnError)
	putCmd.Flags().AddGoFlagSet(fs)//添加go标准库中的flagset至put命令中
	putCmd.Flags().String("type", "", "input type")
	err := putCmd.MarkFlagRequired("type")//为这项命令添加必备参数。
	if err != nil {
		log.Fatalln(err)
	}
	// Here you will define your flags and configuration settings.

	// Cobra supports Persistent Flags which will work for this command
	// and all subcommands, e.g.:
	// putCmd.PersistentFlags().String("foo", "", "A help for foo")

	// Cobra supports local flags which will only run when this command
	// is called directly, e.g.:
	// putCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

开始使用spf13/cobra框架自行编写命令行工具

一个简单的开始

package main

import (
	"fmt"
	"log"

	"github.com/spf13/cobra"
)
//你的子命令都可以通过这种方式创建,这么做可以操作的空间很多
func NewCommand() *cobra.Command {
	//这一块你可以做一些这个命令需要的变量初始化,rune函数里面就可以直接用了
	var cmd = cobra.Command{
		Use:                "demo",
		Short:              "this is a simple sample",
		RunE: func(cmd *cobra.Command, args []string) (err error) {//与rune 对应的还有run,两个都一样,只是返不返回错误的区别,我个人喜欢返回错误出去,最后统一处理。你可以根据自己喜好自行选者
			fmt.Println("this is an example start")
			return
		},
	}
	//这里你可以做些命令行参数绑定什么的
	return &cmd
}

func main() {
	cmd := NewCommand()
	err := cmd.Execute()
	if err != nil {
		log.Fatalln(err.Error())
	}
}

自行控制参数解析,你也可以不用cobra框架,单纯用参数工具pflag(cobra依赖pflag解析参数,你如果依赖了cobra,就不用再go get github.com/spf13/pflag)

package main

import (
	"demo/options"
	"log"
	"time"

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

func getCommandFlags(f *pflag.FlagSet) {
	f.String("type", "", "input type ")
	f.Duration("ttl", time.Second, "ttl")
}
func NewCommand() *cobra.Command {
	var cmd = cobra.Command{
		Use:                "demo",
		Short:              "this is a simple sample",
		DisableFlagParsing: true,//使用我们自带的pflag.FlagSet
		SilenceUsage:       true,//参数传入错误时不会把usage信息弹出来
		RunE: func(cmd *cobra.Command, args []string) (err error) {
			pf := pflag.NewFlagSet("demo", pflag.ContinueOnError)
			getCommandFlags(pf)
			cmd.Flags().AddFlagSet(pf)
			help := pf.BoolP("help", "h", false, "--help")
			err = pf.Parse(args)
			if err == nil {
				if *help {
					return cmd.Help()
				}
			}
			return
		},
	}
	cmd.AddCommand(options.NewPutCommand())
	return &cmd
}

func main() {
	cmd := NewCommand()
	err := cmd.Execute()
	if err != nil {
		log.Fatalln(err.Error())
	}
}

参数解析设置别名

我觉得这是pflag最哇塞的一个功能

func setalias(f *pflag.FlagSet) {
//将所有参数名带-的,使用.也是一样的识别,这里name是参数原始名,返回的是别名。
	f.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
		return pflag.NormalizedName(strings.ReplaceAll(name, "-", "."))
	})
}

最终演示代码

package main

import (
	"demo/options"
	"fmt"
	"log"
	"net"
	"strings"
	"time"

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

var (
	flag_result struct {
		_type string
		ttl   time.Duration
		ip    net.IP
	}
)

func getCommandFlags(f *pflag.FlagSet) {
	f.StringVar(&flag_result._type, "type", "", "input type ")
	f.DurationVar(&flag_result.ttl, "ttl", time.Second, "ttl")
	f.IPVar(&flag_result.ip, "net-ip4", nil, "ip address")
}
func setalias(f *pflag.FlagSet) {
	f.SetNormalizeFunc(func(f *pflag.FlagSet, name string) pflag.NormalizedName {
		return pflag.NormalizedName(strings.ReplaceAll(name, "-", "."))
	})
}
func NewCommand() *cobra.Command {
	var cmd = cobra.Command{
		Use:                "demo",
		Short:              "this is a simple sample",
		DisableFlagParsing: true,
		SilenceUsage:       true,
		RunE: func(cmd *cobra.Command, args []string) (err error) {
			pf := pflag.NewFlagSet("demo", pflag.ContinueOnError)
			getCommandFlags(pf)
			setalias(pf)
			cmd.Flags().AddFlagSet(pf)
			help := pf.BoolP("help", "h", false, "--help")
			err = pf.Parse(args)
			if err == nil {
				if *help {
					return cmd.Help()
				}
				fmt.Println(flag_result._type, flag_result.ttl, flag_result.ip)
			}
			return
		},
	}
	cmd.AddCommand(options.NewPutCommand())
	return &cmd
}

func main() {
	cmd := NewCommand()
	err := cmd.Execute()
	if err != nil {
		log.Fatalln(err.Error())
	}
}

请添加图片描述
请添加图片描述
请添加图片描述

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

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

相关文章

模糊搜索小案例

C#窗体实现数据录入与模糊搜索小案例 记录一下 主要代码 private void button1_Click(object sender, EventArgs e){string name textBox1.Text;string hometown textBox4.Text;string school textBox6.Text;string sex textBox5.Text;string lat textBox3.Text;string …

STM32 (2)

1.stm32编程模型 将C语言程序烧录到芯片中会存储在单片机的flsah存储器中&#xff0c;给芯片上电后&#xff0c;Flash中的程序会逐条进入到CPU中去执行&#xff0c;进而CPU去控制各种模块&#xff08;即外设&#xff09;去实现各种功能。 2.寄存器和寄存器编程 CPU通过控制其…

图像处理ASIC设计方法 笔记6 数据拼接和帧格式校正

第四章大模板卷积ASIC设计方案 P80 实时图SPRM 数据位宽64bit&#xff0c;4个SPRAM&#xff0c;同时得到4行数据 绘制卷积芯片数据路径图&#xff0c;卷积芯片内部模块图 根据这个图&#xff0c;本书后续对各个模块都进行介绍。 P81 第一个模块 图像输入前端FIFO 学习图像处…

【Linux】软件管理yum | 编辑器vim | vim插件安装

目录 1. Linux软件管理yum 1.1 什么是软件包 1.2 查看软件包 1.3 如何安装软件 1.4 如何卸载软件 2. Linux编辑器vim 2.1 vim的基本概念 2.2 vim的基本操作 2.3 vim正常模式命令集 2.4 vim末行模式命令集 2.5 简单vim配置 2.6 插件安装 1. Vim-Plug 3. coc.nvim …

如何保护服务器的安全

互联网的迅速发展&#xff0c;让很多企业都很重视网络技术的使用&#xff0c;但是网络的传播速度比较快&#xff0c;同时容易造成数据、隐私方面的泄露现在每个企业基本有自己的服务器。有几点需要注意&#xff0c;可以参考&#xff1a; 1.基础密码安全 最基本的安全就是密码安…

蜻蜓FM语音下载(mediadown)

一、介绍 蜻蜓FM语音下载&#xff08;mediadown&#xff09;&#xff0c;能够帮助你下载蜻蜓FM音频节目。如果你是蜻蜓FM会员&#xff0c;它还能帮你下载会员节目。 二、下载地址 本站下载&#xff1a;蜻蜓FM语音下载&#xff08;mediadown&#xff09; 百度网盘下载&#…

嵌入式Qt 对话框及其类型 QDialog

一.对话框的概念 对话框是与用户进行简短交互的顶层窗口。 QDialog是Qt中所有对话框窗口的基类。 QDialog继承与QWidfet是一种容器类型的组件。 QDialog的意义&#xff1a; QDialog作为一种专业的交互窗口而存在。 QDialog不能作为子部部件嵌入其他容器中。 QDialog是定制…

js【详解】自动类型转换

运算符 Symbol 数字 会报错 Cannot convert a Symbol value to a number Symbol 字符串 会报错 Cannot convert a Symbol value to a string 存在对象&#xff0c;数组&#xff0c;函数时 对象&#xff0c;数组&#xff0c;函数会先执行其 toString() 方法&#xff0c;…

网络安全概述(一)

目录 资产保护 资产的类型 资产损失类型 资产保护考虑因素 安全强度、安全代价和侵入可能性的关系 信息安全技术发展 单机系统的信息保密阶段 信息保障阶段 信息保障技术框架IATF PDRR模型 网络攻击类型 阻断攻击、截取攻击、篡改攻击、伪造攻击 被动攻击和主动攻…

【设计模式 01】单例模式

单例模式&#xff0c;是一种创建型设计模式&#xff0c;他的核心思想是保证一个类只有一个实例&#xff08;即&#xff0c;在整个应用程序中&#xff0c;只存在该类的一个实例对象&#xff0c;而不是创建多个相同类型的对象&#xff09;&#xff0c;并提供一个全局访问点来访问…

机器学习|KNN和Kmeans

KNN和Kmeans KNN KNN-K个最近的邻居&#xff0c;而K是可人先预设出来的。 所谓近朱者赤&#xff0c;近墨者黑。 可以选取离当前最近的K个样本来作为辅助判断&#xff0c;因为本样本和最近的K个样本应该是处于一种相似的状态。 以下是一个苹果和梨的识别任务。 图上会出现一个未…

JavaScript进阶-高阶技巧

文章目录 高阶技巧深浅拷贝浅拷贝深拷贝 异常处理throw抛异常try/caych捕获异常debugger 处理thisthis指向改变this 性能优化防抖节流 高阶技巧 深浅拷贝 只针对引用类型 浅拷贝 拷贝对象后&#xff0c;里面的属性值是简单数据类型直接拷贝值&#xff0c;如果属性值是引用数…

STM32(8)NVIC编程

中断源由部分片上外设产生 在misc.h中找&#xff0c;杂项 配置NVIC GPIO和AFIO不能产生中断源&#xff0c;但能通过EXTI&#xff0c;由EXTI产生中断源 NVIC不需要开启时钟&#xff0c;因为NVIC模块位于内核内部&#xff0c;芯片一上电就能工作。 中断响应函数 中断向量表在启…

移动感知终端软件发布过程中遇到的问题以及解决方案

一.软件发布 软件的效果展示在文章&#xff1a; 网络图谱构建系统目前已实现的功能-CSDN博客 在android studio编写完程序之后&#xff0c;要打包并发布软件&#xff0c;供其他用户使用&#xff0c;以下几篇文章给出了方法&#xff1a; Android Studio使用签名打包发布APP&…

day09_商品管理订单管理SpringTaskEcharts

文章目录 1 商品管理1.1 添加功能1.1.1 需求说明1.1.2 核心概念SPUSKU 1.1.3 加载品牌数据CategoryBrandControllerCategoryBrandServiceCategoryBrandMapperCategoryBrandMapper.xml 1.1.4 加载商品单元数据ProductUnitProductUnitControllerProductUnitServiceProductUnitMap…

Qt 简约美观的动画 摆钟风格 第十季

&#x1f60a; 今天给大家分享一个摆钟风格的加载动画 &#x1f60a; 效果如下: 最近工作忙起来了 , 后续再分享其他有趣的加载动画吧. 一共三个文件 , 可以直接编译运行 //main.cpp #include "LoadingAnimWidget.h" #include <QApplication> #include <Q…

构建安全的REST API:OAuth2和JWT实践

引言 大家好&#xff0c;我是小黑&#xff0c;小黑在这里跟咱们聊聊&#xff0c;为什么REST API这么重要&#xff0c;同时&#xff0c;为何OAuth2和JWT在构建安全的REST API中扮演着不可或缺的角色。 想象一下&#xff0c;咱们每天都在使用的社交媒体、在线购物、银行服务等等…

Spring框架精髓:带你手写IoC

个人名片&#xff1a; &#x1f43c;作者简介&#xff1a;一名大三在校生&#xff0c;喜欢AI编程&#x1f38b; &#x1f43b;‍❄️个人主页&#x1f947;&#xff1a;落798. &#x1f43c;个人WeChat&#xff1a;hmmwx53 &#x1f54a;️系列专栏&#xff1a;&#x1f5bc;️…

C语言之OJ刷题

今天刷一下题 刷的不多 第一道 链表的回文结构 仔细看这个题它是有限制条件的 首先是时间复杂度和空间复杂度 所以我们并不是用数组去做 但怎么做呢&#xff1f; 思路 既然是判断是否是回文结构&#xff0c;那么我们就找一下他的中间节点 然后将后半段倒置 进行比较…

【简说八股】Redisson的守护线程是怎么实现的

Redisson Redisson 是一个 Java 语言实现的 Redis SDK 客户端&#xff0c;在使用分布式锁时&#xff0c;它就采用了「自动续期」的方案来避免锁过期&#xff0c;这个守护线程我们一般也把它叫做「看门狗」线程。 Redission是一个在Java环境中使用的开源的分布式缓存和分布式锁实…