首页 > 编程语言 >go语言命令行程序(CLI)开发工具小记

go语言命令行程序(CLI)开发工具小记

时间:2023-11-10 21:31:39浏览次数:31  
标签:CLI app 开发工具 flag 命令行 go main name

go语言命令行程序(CLI)开发工具小记_框架

Go语言领域,命令行程序占据比较重要的位置。因此,命令行程序的快速开发及工具选择就成为一个不可忽视的问题。本文简要总结使用Go语言开发命令行程序中常用的几个框架。

一、Cobra

Cobra 是关于 golang 的一个命令行解析库,用它能够快速创建功能强大的 cli 应用程序和命令行工具。

cobra既是一个用于创建强大现代CLI应用程序的库,也是一个生成应用程序和命令文件的程序。cobra被用在很多go语言的项目中,比如 Kubernetes、Docker、Istio、ETCD、Hugo、Github CLI等等。

hugo:号称速度最快的静态站点生成器。

我们平常用到命令:git commit -m “message”,docker containter start 等都可以用 cobra 来实现。

  • Cobra 官网:https://cobra.dev/
  • github地址:https://github.com/spf13/cobra

功能特性介绍

  • 很多子命令的CLIS: 比如 app server、app fetch 等
  • 支持嵌套子命令(sub-command)
  • 轻松完成应用程序和命令的创建:cobra init appname 和 cobra add cmdname
  • 为应用程序生成 man 手册
  • 全局、本地和级联 flag
  • 为 shell 程序完成自动提示(bash,zsh,fish, powershell etc.)
  • 支持命令行别名,可以帮助你更容易更改内容而不破坏他们
  • 灵活定义自己的help、usage信息
  • 可选集成 viper 配置管理工具库

Cobra命令结构说明

Cobra 命令结构由3部分组成:

commands、arguments 和 flags

commands:

命令行,代表行为动作,要执行的一个动作。每个命令还可以包含子命令,分为:rootCmd 和 subCmd。程序中具体对象是 cobra.Command{},这个是根命令;子命令(subCmd)用 rootCmd.AddCommand() 添加,子命令通常也会单独存一个文件,并通过一个全局变量让 rootCmd 可以 add 它。

arguments:

命令行参数,通常是 []string 表示。

flags:

命令行选项。对 command 进一步的控制。通常用一短横 - 或者两短横 -- 标识,程序中读取存储在变量中。

cobra 命令行格式:

APPNAME VERB NOUN --ADJECTIVE

APPNEM COMMAND ARG --FLAG

例子说明:

# server代表command,port代表flag

hugo server --port=1313

# clone代表command,URL代表argument,bare代表flag

git clone URL --bare



二、go语言内置flag库

Flag库是golang自带的命令行参数库。可以通过 -name abc的方式 或者-name=abc 的方式来给命令行参数name传入 abc这个值。

1. 简单使用命令行参数的情况

  1. 需要特别注意 一定不要忘记调用 flag.Parse() 否则你的参数都是默认值。
  2. 另外需要注意StringVar 中第一个参数一定是变量的指针 这样才能将解析到的值添加到变量中。
package main

import (
   "flag"
   "fmt"
)

// 适用于最简单的 只有一组命令行参数的情况

// 带有等号的格式
// eg: go run main.go -name=ikun -id=29238 -male

// 不带有等号的格式
// eg: go run main.go -name ikun -id 29238 -male
func main() {
   var name string
   var studentId int
   var isMale bool

   // 定义 flag.xxxVar(&变量, 参数名, 默认值, 帮助信息)
   flag.StringVar(&name, "name", "caixukun.666", "姓名")
   flag.IntVar(&studentId, "id", 128, "学号")
   flag.BoolVar(&isMale, "male", false, "是男性")

   // 注意一定要有解析 否则变量都是默认值
   flag.Parse()

   // 查看解析结果
   fmt.Printf("Name=%s, StudentId=%d, IsMale=%t\n", name, studentId, isMale)
}

2. 有子命令的情况

类似于docker container -ls 中container 就是一个子命令

1. 这种情况下需要首先解析一次。否则flag.Args是无效的。

2. 使用flag.Args()[0] 来判断使用的是哪个子命令

3. 然后重新创建一个命名的flagSet 进一步解析 flag.Args[1:] 部分的命令行参数作为子命令的命令行参数

package main

import (
   "flag"
   "fmt"
)

// 适用于有子命令的情况

// 不带有等号的格式
// eg:  student子命令: go run main.go student -name ikun -id 29238 -male
// eg:  student子命令: go run main.go teacher -name mayun -salary 20000

// 带有等号的格式
// eg:  student子命令: go run main.go student -name=ikun -id=29238 -male
// eg:  student子命令: go run main.go teacher -name=mayun -salary=20000
func main() {
   //首先要用全局默认FlagSet解析一遍 否则flag.Args是无效的。
   flag.Parse()
   flagArgs := flag.Args()
   switch flagArgs[0] {
   case "student":// student子命令解析
      var name string
      var studentId int
      var isMale bool
      stuendtFlags := flag.NewFlagSet("student", flag.ExitOnError)
      stuendtFlags.StringVar(&name, "name", "caixukun.666", "姓名")
      stuendtFlags.IntVar(&studentId, "id", 128, "学号")
      stuendtFlags.BoolVar(&isMale, "male", false, "是否男性")

      // 索引从1开始 索引0是子命令 "student" 字符串
      err := stuendtFlags.Parse(flagArgs[1:])
      if err != nil {
         fmt.Printf("Student Invalid cmd option\n")
         return
      }
      fmt.Printf("Student: Name=%s, StudentId=%d, IsMale=%t\n", name, studentId, isMale)
   case "teacher":
      var name string
      var salary int64
      teacherFlags := flag.NewFlagSet("teacher", flag.ExitOnError)
      teacherFlags.StringVar(&name, "name", "caixukun.666", "姓名")
      teacherFlags.Int64Var(&salary, "salary", 128, "薪资")
      err := teacherFlags.Parse(flagArgs[1:])
      if err != nil {
         fmt.Printf("Teacher Invalid cmd option\n")
         return
      }
      fmt.Printf("Teacher: Name=%s, Salary=%d\n", name, salary)
   default:
      fmt.Printf("Invalid cmd option\n")
   }
}

三、mow.cli

地址:https://github.com/jawher/mow.cli

著名的基于Go语言的爬虫框架colly就是基于此命令行框架。

简单举例,更复杂的见官网:

package main

import (
	"fmt"
	"os"

	"github.com/jawher/mow.cli"
)

func main() {
	// create an app
	app := cli.App("cp", "Copy files around")

	// Here's what differentiates mow.cli from other CLI libraries:
	// This line is not just for help message generation.
	// It also validates the call to reject calls with less than 2 arguments
	// and split the arguments between SRC or DST
	app.Spec = "[-r] SRC... DST"

	var (
		// declare the -r flag as a boolean flag
		recursive = app.BoolOpt("r recursive", false, "Copy files recursively")
		// declare the SRC argument as a multi-string argument
		src = app.StringsArg("SRC", nil, "Source files to copy")
		// declare the DST argument as a single string (string slice) arguments
		dst = app.StringArg("DST", "", "Destination where to copy files to")
	)

	// Specify the action to execute when the app is invoked correctly
	app.Action = func() {
		fmt.Printf("Copying %v to %s [recursively: %v]\n", *src, *dst, *recursive)
	}

	// Invoke the app passing in os.Args
	app.Run(os.Args)
}


参考




标签:CLI,app,开发工具,flag,命令行,go,main,name
From: https://blog.51cto.com/zhuxianzhong/8308928

相关文章

  • 渗透学习1.1 信息收集之google hacking
    0x0前言  google是一款非常强大的搜索引擎,相对来说广告较少,查询结果全面,通常我们的使用方式是在搜索框输入想要查询的词汇,一般来说我们很容易搜索到想要的结果,但是Google也可以通过特定的语法对查询结果进行筛选,甚至可以对网页内容,文件,路径,建站模板等进行匹配,便于我们发现可......
  • China's Ongoing Efforts In Combating Air Pollution
    AnewstudyhasbeenconductedtounderstandwhethertherecentchangesinChina'sairqualityweredrivenbymeteorologicalinfluencesorairpollutantemissionreductionefforts.ItwasledbyProf.YinchangFengfromtheCollegeofEnvironmentalS......
  • Django3
    数据的增删改查如何创建表关系Django框架的请求生命周期流程图路由曾无名分组有名分组——————————————————————————————————————————————————————————————————————————————————————......
  • Django2
    三板斧的使用全局配置文件静态文件的配置request对象的几个方法Pycharm链接数据库MysqlDjango联机而数据库Mysql——————————————————————————————————————————————————————————————————————————......
  • 聊点技术|100%降本增效!Bonree ONE 通过 Clickhouse实现了
    10月20日,数智融,ONE向新——博睿数据2023秋季产品发布会圆满落幕,全新一代一体化智能可观测平台BonreeONE2023秋季正式版焕新发布,重点升级了数据采集、全局拓扑、数据分析、会话回放等多个功能模块,为组织提供了更加轻盈、有序、精准的超智能运维体验。文章信息作者|博睿数据数智中心......
  • django中数据库外键可以自定义名称吗
    是的,在Django中,你可以自定义数据库外键的名称。在定义模型时,可以使用`db_constraint`参数来设置外键的约束名称。默认情况下,Django会自动生成外键约束的名称,但你可以通过设置`db_constraint`参数为`False`来禁用自动生成的约束,并且在需要时手动为外键指定名称。以下是一个简单的例......
  • Go语言中切片和数组有什么区别
    在Go语言中,数组的结构非常简单,它由两个部分组成:数据类型(DataType):数组中包含的元素的数据类型是固定的,所有元素必须具有相同的数据类型。这意味着一个数组可以包含整数、浮点数、字符串或其他数据类型,但所有元素的类型必须一致。长度(Length):数组的长度是在声明时指定的,它表示数组中......
  • 设计模式 - Immutable 模式(Java不变集合类 vs Google Guava不变集合类)
    总结JDK中的unmodifiableList的构造函数是对原始集合的浅拷贝,而Guava.ImmutableList.copyOf是对原始集合的深拷贝 publicclassImmutableDemo{publicstaticvoidmain(String[]args){List<String>originalList=newArrayList<>();originalList.add("a"......
  • vue-cli-service vue.config.js配置 productionSourceMap与webpack中的devtool 关联详
    https://webpack.js.org/configuration/devtool/https://cli.vuejs.org/zh/config/#productionsourcemap https://github.com/vuejs/vue-cli/blob/f0f254e4bc81ed322eeb9f7de346e987e845068e/packages/%40vue/cli-service/lib/config/prod.js#L7 可以在源码中看到if(pro......
  • A potentially dangerous Request.Form value was detected from the client
    ApotentiallydangerousRequest.Formvaluewasdetectedfromtheclient解决方案一:在.aspx文件头中加入这句:<%@PagevalidateRequest="false" %>解决方案二:修改web.config文件:<configuration> <system.web>   <pagesvalidateRequest="fals......