前言

针对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. UTS Open '21 P7 - April Fools

    传送门 前言 本题是笔者keysky与同学yangbaich讨论+推式子一整个晚上以及讨论前ybc的一整个下午做出来的,综合起来是 \(34\) 个转移方程,对于整道题来说,贡献大抵为我 \(2\) ...

  2. Linux VXLAN小实验

    本文分享自天翼云开发者社区<Linux VXLAN小实验>,作者:李****一 前言 VXLAN在云网络中应用十分广泛.本文介绍一种方法在两台Linux主机之间建立简单的VXLAN隧道,以 ...

  3. HPC云化部署的优势和挑战

    本文分享自天翼云开发者社区<HPC云化部署的优势和挑战> 作者:土豆炒肉丝 HPC云化部署指的是将高性能计算(HPC)工作负载部署在云计算平台上,这种方式带来了一些明显的优势,但同时也面临 ...

  4. mysql之PreparedStatement的增删改

    编写配置文件[db.properties]: driver=com.mysql.jdbc.Driver url=jdbc:mysql://localhost:3306/jdbcStudy?useUni ...

  5. Springboot 3.x 使用PageHelper实现MyBatis分页查询

    开发环境 SpringBoot 3.0.1 Maven 工程 JDK OpenJdk 17.0.6 引入pom依赖 <dependency> <groupId>com.gith ...

  6. STC内部扩展RAM的应用

    RAM是用来在程序运行中存放随机变量的数据空间,51单片机默认的内部RAM只有128字节,52单片机增加至256字节,STC89C52增加到512字节,STC89C54.55.58.516等增加到12 ...

  7. jQuery validate验证表单隐藏域

    function validInfoForm(){        return $("#form_password").validate({            ignore : ...

  8. Javascript Object对象转Map

    1. Object对象 const data = { "banana": [ { "color": "yellow", "coun ...

  9. kalibr标定单相机,自用指南,防忘记

    1. 标定环境 1.1 从源码编译(linux环境,建议ubuntu 18或20) 步骤见 kalibr wiki 1.2 Docker 如果实体机为Ubuntu,则见official docker ...

  10. Azkaban - [01] 概述

    简单的任务调度使用crontab.复杂的任务调度使用oozie.azkaban等开发调度系统. 一.为什么学习Azkaban   一个完整的数据分析系统通常都是由大量任务单元(shell脚本.java ...