0
点赞
收藏
分享

微信扫一扫

QT----写完的程序打包为APK在自己的手机上运行

mafa1993 03-05 07:30 阅读 4

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())
	}
}

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

举报

相关推荐

0 条评论