首页 > 其他分享 >CLI命令行应用

CLI命令行应用

时间:2023-04-20 09:44:09浏览次数:42  
标签:jam cobra CLI age 命令行 flag version 应用 gotour

前言

针对golang这门高级语言,主要想了解它的语言特性还有服务器建站还有微服务搭建方面的用途,以下都可以算是使用记录。

一、命令行应用的标准库实现

很多语言都有针对命令行参数的功能包,比如python的argparse和golang的flag两个标准库,对于不少c/cpp程序员来说,最直显的就是main函数的argc和argv两个运行参数了,使用效果就是平时输入命令的各种参数:

# 删库跑路专用
rm -rf /*

如上面的rm命令,rf就是它的执行参数,负责告知rm,把根目录下所有文件、文件夹和子文件夹都给我干掉的意思并且是强行删除不问询。高级语言针对针对命令行参数已经封装好只需要调用函数传入参数即可,不像c/cpp还需要针对输入参数来写逻辑处理,同样的场景有不同的使用,相对而言高级语言拿来就用不用造轮子是为了方便实现,c/cpp很多都是自定义的造轮子所以更像原有功能不满意所以自己造一个来用,算是有深入了解的高手的语言吧。

1.1 实现一个简单带命令参数的应用

golang标准库flag的使用比较简单,如下:

func main(){
    var name string
    flag.StringVar(&name, "name", "作者", "帮助信息")
    flag.StringVar(&name, "n", "author", "帮助信息")

    var age int
    flag.IntVar(&age, "age", 18, "年龄")
    flag.IntVar(&age, "a", 80, "年龄")
    flag.Parse()

    fmt.Printf("author: %s, age: %d\n", name, age)
}

输出如下:

# golang可以直接run也可以进行编译再运行,这里编译了可执行文件再执行
jam:~$ go build .
jam:~$ ./gotour -h
Usage of ./gotour:
  -a int
        age (default 80)
  -age int
        年龄 (default 18)
  -n string
        帮助信息 (default "aaa")
  -name string
        帮助信息 (default "bbb")
jam:~$ ./gotour
author: bbb, age: 80
jam:~$ ./gotour -n jack
author: jack, age: 80
jam:~$ ./gotour --name=jam
author: jam, age: 80
jam:~$ ./gotour -age 29
author: bbb, age: 29
jam:~$ 

简单的应用就是使用flag的StringVar或者IntVar或BoolVal等api来设置具体类型的参数,都是四个参数,第一个是存储信息的变量,第二个是参数名比如上面的rf,第三个则是这个参数的默认值,如果没有输入该参数,变量就存储默认值,最后一个参数则是提示之类的信息,比如很多linux命令都有help参数,这个就是默认help参数的针对对应参数的解释提示。在上面特定参数设置好以后,进行Parse()调用,就算整体设置完毕。

另一种实现

除了上面四参数的各种Var库函数,还有下面这种:

func main() {
	flag.Parse()
	name := flag.String("name", "jam", "作者")
	age := flag.Int("a", 18, "作者年龄")

	fmt.Printf("the author: %s, age: %d\n", *name, *age)
}

输出如下:

jam:$ go build .
jam:$ ./gotour 
the author: jam, age: 18
jam:$ ./gotour -h
Usage of ./gotour:
  -a int
        作者年龄 (default 18)
  -name string
        作者 (default "jam")
jam:$ ./gotour --name Peter
the author: Peter, age: 18
jam:$ ./gotour -a 88
the author: jam, age: 88

要注意的是,针对同一个命令比如上面注明作者这个命令,是哪个调用在前,就使用哪个默认值,另外就是Parse的调用可以在参数设置完以后也可以一开始就调用。还有就是注意别设置重复的命令参数,冲突起来大概就只能谁先谁后了。

1.2 实现有子命令的应用

当一个命令应用具备越来越多的功能时,就会变得臃肿,需要几个主命令参数,其下子命令负责更细致的划分,比如用的较多的linux安装命令:

# centos
yum list installed

# ubuntu
apt list --installed

上面两个命令的执行可以得到各自系统的对应已安装包列表(不过安装方式要对应yum或者apt就是了),上面list参数就是列出列表的意思,后面installed参数则是指明列表内容,它就是对应list的命令集下的子命令了。使用flag标准库实现一下:

func main() {
	flag.Parse()
	args := flag.Args()

	if len(args) <= 0 {
		return
	}

	switch args[0] {
	case "cat":
		showCmd := flag.NewFlagSet("cat", flag.ExitOnError)
		showCmd.StringVar(&something, "s", "abaaba", "简单输出")
		showCmd.StringVar(&something, "sentence", "小aba", "输出")
		_ = showCmd.Parse(args[1:])
	case "want":
		wantCmd := flag.NewFlagSet("want", flag.ExitOnError)
		wantCmd.StringVar(&something, "book", "计算机科学", "书名")
		wantCmd.StringVar(&something, "b", "计算机网络", "书名")
		_ = wantCmd.Parse(args[1:])
	}

	fmt.Printf("the something:%s\n", something)
}

输出如下:

jam:~$ ./gotour 
jam:~$ ./gotour -h
Usage of ./gotour:
jam:~$ ./gotour cat
the something:小aba
jam:~$ ./gotour want -b 火影忍者
the something:火影忍者
jam:~$ 

二 命令行应用的cobra库实现

因为要用到外部库cobra, 所以先安装一下吧,我这里的IDE是goland和配置好了的vscode环境,但都需要在对应位置输入下面命令:

go get -u github.com/spf13/cobra

关于库的使用,都是了解个用法,重要还是例子:

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "版本号",
	Long:  "输出版本号",
	Run: func(cmd *cobra.Command, args []string) {
		version := "1.0.0"
		if len(args) > 1 {
			version = args[1]
		}
		fmt.Println("gocmd version :", version)
	},
}

func main() {
	err := versionCmd.Execute()
	if err != nil {
		log.Fatal("命令执行失败:%v", err)
	}
}

输出如下:

jam:~$  go build
jam:~$  ./cmdpra -h
输出版本号

Usage:
  version [flags]

Flags:
  -h, --help   help for version
jam:~$  ./cmdpra version 2.0.0
gocmd version : 2.0.0

对照flag标准库,cobra的使用也需要四部分信息:命令参数, 短描述, 长描述和命令处理(和flag稍微有点不同), cobra内置了Command数据结构来存储对应信息,命令的调用也就是一个Command对象调用Execute即可,如上是单个命令的实现,
要实现多个命令统一子命令就需要使用cobra的AddCommand接口了:

var catCmd = &cobra.Command{
	Use:   "cat",
	Short: "something",
	Run: func(cmd *cobra.Command, args []string) {
		s := "nothing"
		if len(args) > 1 {
			s = args[1]
		}
		fmt.Println("cat ", s)
	},
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "版本号",
	Long:  "输出版本号",
	Run: func(cmd *cobra.Command, args []string) {
		version := "1.0.0"
		if len(args) > 1 {
			version = args[1]
		}
		fmt.Println("gocmd version :", version)
	},
}

func main() {
	rootCmd := &cobra.Command{}
	rootCmd.AddCommand(catCmd)
	rootCmd.AddCommand(versionCmd)
	err := rootCmd.Execute()
	if err != nil {
		log.Fatal("命令执行失败:%v", err)
	}
}

不过一般来说,项目会根据情况进行解偶,所以这些个子命令的设置一般会设定在cmd包里,再来内部调用,到时候main包就只需要进行一个Execute即可,上面输出如下:

jam:~$ ./cmdpra 
Usage:
   [command]

Available Commands:
  cat         something
  help        Help about any command
  version     版本号

Flags:
  -h, --help   help for this command

Use " [command] --help" for more information about a command.
jam:~$ ./cmdpra cat abaaba
cat  nothing

除此以外,添加子命令的方式也可以类似标准库的StringVar,如下:

var str string

var catCmd = &cobra.Command{
	Use:   "cat",
	Short: "something",
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Printf("gocmd version: %s\n", str)
	},
}

func main() {
	rootCmd := &cobra.Command{}
	rootCmd.AddCommand(catCmd)
	catCmd.Flags().StringVarP(&str, "version", "v", "v1.0.0", "版本号")
	err := rootCmd.Execute()
	if err != nil {
		log.Fatal("命令执行失败:%v", err)
	}
}

flag标准库的StringVar需要四个参数,两次调用就可以有v和version两个子命令参数的实现,cobra.StringVarP一个接口五个参数就实现,算是可以打字少一点。对应输出就是下面了:

jam:~$ ./cmdpra cat --version=v2.0.0
gocmd version: v2.0.0
jam:~$ ./cmdpra cat
gocmd version: v1.0.0
jam:~$ ./cmdpra
Usage:
   [command]

Available Commands:
  cat         something
  help        Help about any command

Flags:
  -h, --help   help for this command

Use " [command] --help" for more information about a command.
jam:~$ 

标签:jam,cobra,CLI,age,命令行,flag,version,应用,gotour
From: https://www.cnblogs.com/Jack-artical/p/17331780.html

相关文章

  • 信号隔离器在水处理控制系统的应用
    安科瑞虞佳豪随着科学技术的深入推进与不断提高,自动化监测技术的逐渐完善是污水处理厂未来发展的一种必然趋势,充分了解污水处理厂的自动化需求、各个处理单元的监测以及污水处理厂自动化监测技术的现状,对于我国污水处理未来自动化的发展具有重要意义。污水处理厂未来自动化的需求,......
  • Qt编写推流综合应用示例(文件推流/桌面推流/本地摄像头/网络摄像头/转发推流/视频分发)
    一、功能特点1.1文件推流指定网卡和监听端口,接收网络请求推送音视频等各种文件。实时统计显示每个文件对应的访问数量、总访问数量、不同IP地址访问数量。可指定多种模式,0-直接播放、1-下载播放。实时打印显示各种收发请求和应答数据。每个文件对应MD5加密的唯一标识符,用......
  • Solon v2.2.12 发布,Java 应用开发框架
    Solon是一个高效的Java应用开发框架:更快、更小、更简单。它不是Spring、没有使用Servlet、JavaEE接口,是一个有自己接口标准的开放生态:150多个生态插件,可以满足各种场景开发大量的国产框架适配,可以为应用软件国产化提供更好支持,助力信创建设相对于SpringBoot和Sprin......
  • Docker CLI docker compose events常用命令
    Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的镜像中,然后发布到任何流行的Linux或Windows操作系统的机器上,也可以实现虚拟化。Docker是内核虚拟化,不使用Hypervisor是不完全虚拟化,依赖内核的特性实现资源隔离。本文主要介绍DockerCLI中d......
  • Eclipse console UTF-8编码的设置
    建置全UTF-8的環境:1.在eclipse.ini的-vmargs下面加上-Dfile.encoding=UTF-82.eclipse-->Window-->Preferences-->General-->Workspace-->Textfileencoding-->UTF-83.InstalledJREs-->DefaultVMArguments:-->-Dfile.encoding=UTF-84.eclipse-->Run-->......
  • 2012 年最佳 Android 应用
    2012年最佳Android应用  •Evernote:云笔记应用•Zappos:美国鞋类电商Zappos官方应用•Pinterest:图片社交网络•Grimm’sSnowWhite:游戏《格林童话:白雪公主》•Expedia:在线旅游网站•Pocket:“稍后再读”应用•Ancestry:家谱网站Ancestry官方应用•Fancy:创意收集应用•......
  • best practise for eclipse launch arguments
    -vmargs-Dosgi.requiredJavaVersion=1.5-Dsun.net.client.defaultReadTimeout=3000000-Xms128M-Xmx512M-XX:PermSize=128M-XX:MaxPermSize=256M-XX:+UseParallelGC-Dorg.eclipse.ecf.provider.filetransfer.excludeContributors=org.eclipse.ecf.provider.filetransfe......
  • C/C++哈希表应用[2023-04-19]
    C/C++哈希表应用[2023-04-19]选题二十:哈希表应用[问题描述]利用哈希表进行存储任务要求:针对一组数据进行初始化哈希表,可以进行显示哈希表,查找元素,插入元素,删除元素退出程序操作。设计思想:哈希函数用除留余数法构造,用线性探测再散列处理冲突。设计目的:实现哈希表的综合操......
  • ClickHouse数据迁移工具之clickhouse-copier
    ClickHouse数据迁移工具之clickhouse-copierclickhouse需要从单节点迁移至副本集群中,表结构统一修改为副本表网上搜到的迁移方式大致为三种。一、拷贝数据目录操作流程在源集群的硬盘上打包好对应数据库或表的data和metadata数据拷贝到目标集群对应的目录重启clickhou......
  • 在 Clion 中使用 vcpkg 包管理器
    在Clion中使用vcpkg包管理器0、前置条件:Win7or更新的版本安装Git安装VisualStudio2015Update3或更新的版本(不需要完整安装,只需要安装好调试器以及编译器)一、安装vcpkg去官方GitHub仓库下载项目:gitclonehttps://github.com/microsoft/vcpkg执行项目......