前言

针对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:~$

CLI命令行应用的更多相关文章

  1. ThinkPHP3.1.2 使用cli命令行模式运行

    ThinkPHP3.1.2 使用cli命令行模式运行 标签(空格分隔): php 前言 thinkphp3.1.2 需要使用cli方法运行脚本 折腾了一天才搞定 3.1.2的版本真的很古老 解决 增加 ...

  2. PHP的CLI命令行运行模式浅析

    在做开发的时候,我们不仅仅只是做各种网站或者接口,也经常需要写一些命令行脚本用来处理一些后端的事务.比如对数据进行处理统计等.当然也是为了效率着想,当一个事务有可能会有较长的耗时时,往往会交由服务器的 ...

  3. golang常用库:cli命令行/应用程序生成工具-cobra使用

    golang常用库:cli命令行/应用程序生成工具-cobra使用 一.Cobra 介绍 我前面有一篇文章介绍了配置文件解析库 Viper 的使用,这篇介绍 Cobra 的使用,你猜的没错,这 2 个 ...

  4. Jenkins CLI命令行

    Jenkins CLI命令行 jenkins不光可以UI操作还提供了命令行接口 位置 首页->系统管理->工具和动作->Jenkins 命令行接口 在这个界面下载一个jenkins- ...

  5. Apache Commons CLI命令行启动

    今天又看了下Hangout的源码,一般来说一个开源项目有好几种启动方式--比如可以从命令行启动,也可以从web端启动.今天就看看如何设计命令行启动... Apache Commons CLI Apac ...

  6. GO语言之urfave/cli命令行解析

    练习URL: https://blog.csdn.net/sd653159/article/details/83381786 相信只要部署过线上服务,都知道启动参数一定是必不可少的,当你在不同的网络. ...

  7. Angular CLI 命令行工具

    工欲善其事必先利其器.好的工具让开发更加简单便捷. 1.全局安装angular cli npm install -g @angular/cli 2.安装完成后就可以使用angular-cli命令行工具 ...

  8. CI 框架下执行CLI(命令行)

    1.可以按照Ci官方文件的指导来进行操作 让我们先创建一个简单的控制器,打开你的文本编辑器,新建一个文件并命名为 Tools.php,然后输入如下的代码: <?php class Tools e ...

  9. Go语言中的IO操作、Flag包以及urfave/cli命令行框架

    一.格式化输入和输出 1.从终端获取用户的输入 fmt.Scanf  空格作为分隔符,占位符和格式化输出的一致 fmt.Scan  从终端获取用户的输入,存储在Scanln中的参数里,空格和换行符作为 ...

  10. 开发CLI命令行

    命令行工具:CLI 是在命令行终端使用的工具,如git, npm, vim 都是CLI工具.比如我们可以通过 git clone 等命令简单把远程代码复制到本地 和 cli 相对的是图形用户界面(gu ...

随机推荐

  1. 第五章 ReentrantLock源码解析

    最常用的方式: int a = 12; //注意:通常情况下,这个会设置成一个类变量,比如说Segement中的段锁与copyOnWriteArrayList中的全局锁 final Reentrant ...

  2. ClickHouse-4SQL参考

    SQL参考 ClickHouse支持以下形式的查询: SELECT INSERT INTO CREATE ALTER 其他类型的查询 ClickHouse SQL 语句 语句表示可以使用 SQL 查询 ...

  3. 使用 pdf.js 通过文件流方式加载pdf文件

    关于Pdf.js的基础知识,请参考我的博客  使用 pdf.js 在网页中加载 pdf 文件 使用 pdf.js 跨域问题的处理方法 上面两篇博客中介绍的内容都是基于直接加载远程服务器中静态PDF文件 ...

  4. Practical Secure Aggregation for Privacy-Preserving Machine Learning

    1 介绍 本文是谷歌团队发在CCS2017上的文章,旨在解决联邦学习中安全聚合的问题. 安全聚合:多方参与者将信息传递给聚合者,聚合者除了知道这个信息的总和不能知道任何一个特定参与者的信息. 在这篇文 ...

  5. 0101-JDK和tomcat的安装配置

    一.JDK8安装与配置 分别配置如下三个系统变量 JAVA_HOME设置变量值为java JDK的安装目录例如: C:\Program Files\Java\jdk1.8.0 PATH添加变量值 %J ...

  6. java中的文件流File

    数据 + 流(转)操作 IO I表示的是:输入Input O表示的是:Output Stream表示流转 java中的管道不止一个.并且管道有可能不是一样的. 有的管道粗有的管道细 File的常用方法 ...

  7. 浅谈云主机在VPC中进行迁移的使用场景和操作方法

    本文分享自天翼云开发者社区<浅谈云主机在VPC中进行迁移的使用场景和操作方法>,作者:刘****雪 一.客户经常遇到的网络迁移问题 客户在天翼云购买一台云主机并且部署完成想要的应用后,发现 ...

  8. VS Code 开发工具的基本使用

    VS Code 开发工具的基本使用 VS Code(Visual Studio Code)是微软开发的一款免费.开源的代码编辑器,它支持多种操作系统,包括Windows.macOS和Linux.VS ...

  9. 『Python底层原理』--CPython如何运行Python代码

    Python作为一种广泛使用的编程语言,其简洁的语法和强大的功能深受开发者喜爱. 然而,对于许多Python用户来说,CPython(Python的官方实现)的内部工作机制仍然是一个神秘的黑盒. 今天 ...

  10. xcode 12.3 mac m1