当前位置: 首页 > news >正文

交互:可以执行命令行的框架才是好框架

上一节课,我们开始把框架向工业级迭代,重新规划了目录,这一节课将对框架做更大的改动,让框架支持命令行工具。

第三方命令行工具库 cobra

obra 不仅仅能让我们快速构建一个命令行,它更大的优势是能更快地组织起有许多命令行工具,因为从根命令行工具开始,cobra 把所有的命令按照树形结构组织起来了。

在这里插入图片描述
cobra库最核心的数据结构Command:

一个 Command 代表一个执行命令。这个 Command 包含很多可设置的字段,如何使用这个 Command,就取决于我们如何设置这些属性。下面是源码片段,我在注释中列出了这些属性的意义。


// Command代表执行命令的结构
type Command struct {// 代表当前命令的,如何执行,root 最好和生成的命令工具名称一致Use string// 代表这个工具的别名,在 subCommand 中有用,比如 root cmd1 和 root cmd_1 想要都执行一个 subCommand 就需要这样Aliases []string// 由于不强制设置,用于输入错误的时候建议字段SuggestFor []string// 这个就是在 help 的时候一句话描述这个命令的功能Short string// 详细描述这个命令的功能Long string// 例子Example string// 需要验证的参数ValidArgs []string// 有多少个参数,这里放了一个验证函数,可以是 ExactArgs,MaximumNArgs 等,验证有多少个参数Args PositionalArgs// 参数别名ArgAliases []string// 自动生成的命令设置BashCompletionFunction string// 如果这个命令已经废弃了,那么就这里写上废弃信息Deprecated string// 如果这个命令要被隐藏,设置这个字段Hidden bool// Annotations are key/value pairs that can be used by applications to identify or// group commands.Annotations map[string]string// 这个命令的版本Version string// 是否要打印错误信息SilenceErrors bool// 是否要打印如何使用SilenceUsage bool// 是否有 flag,如果这个命令没有 flag,设置为 true,那么所有的命令后面的参数都会是 argumentsDisableFlagParsing bool// 是否打印自动生成字样: ("Auto generated by spf13/cobra...")DisableAutoGenTag bool// 是否显示[flags]字样DisableFlagsInUseLine bool// 是否打印建议DisableSuggestions bool// 两个字符串的差距多少会进入 suggestSuggestionsMinimumDistance int// 是否使用 Traverse 的方式来解析参数TraverseChildren bool// 解析错误白名单, 比如像未知参数FParseErrWhitelist FParseErrWhitelist// The *Run 函数运行顺序://   * PersistentPreRun()//   * PreRun()//   * Run()//   * PostRun()//   * PersistentPostRun()// 会被继承的前置 RunPersistentPreRun func(cmd *Command, args []string)// 会被继承的前置 Run, 带 errorPersistentPreRunE func(cmd *Command, args []string) error// 当前这个命令的前置 RunPreRun func(cmd *Command, args []string)// 当前这个命令的前置 Run,带 ErrorPreRunE func(cmd *Command, args []string) error// zh: 实际跑的时候运行的函数Run func(cmd *Command, args []string)// zh: Run 执行错误了之后RunE func(cmd *Command, args []string) error// 后置运行PostRun func(cmd *Command, args []string)// 后置运行,带 errorPostRunE func(cmd *Command, args []string) error// 会被继承的后置运行PersistentPostRun func(cmd *Command, args []string)// 会被继承的后置运行,带 errorPersistentPostRunE func(cmd *Command, args []string) error}

具体使用的一个场景:


// InitFoo 初始化 Foo 命令
func InitFoo() *cobra.Command {FooCommand.AddCommand(Foo1Command)return FooCommand
}
// FooCommand 代表 Foo 命令
var FooCommand = &cobra.Command{Use:     "foo",Short:   "foo 的简要说明",Long:    "foo 的长说明",Aliases: []string{"fo", "f"},Example: "foo 命令的例子",RunE: func(c *cobra.Command, args []string) error {container := c.GetContainer()log.Println(container)return nil},
}
// Foo1Command 代表 Foo 命令的子命令 Foo1
var Foo1Command = &cobra.Command{Use:     "foo1",Short:   "foo1 的简要说明",Long:    "foo1 的长说明",Aliases: []string{"fo1", "f1"},Example: "foo1 命令的例子",RunE: func(c *cobra.Command, args []string) error {container := c.GetContainer()log.Println(container)return nil},
}
  • Use 代表这个命令的调用关键字,比如要调用 Foo1 命令,我们就要用 ./hade foo foo1 。Short 代表这个命令的简短说明,它会出现在上级命令的使用文档中。
  • Long 代表这个命令的长说明,它会出现在当前命令的使用文档中。
  • Aliases 是当前命令的别名,等同于 Use 字段;
  • Example 是当前命令的例子,也是显示在当前命令的使用文档中。

而 RunE 代表当前命令的真正执行函数:

RunE: func(c *cobra.Command, args []string) error 

这个执行函数的参数有两个:一个是 cobra.Command,表示当前的这个命令;而第二个参数是 args,表示当前这个命令的参数,返回值是一个 error,代表命令的执行成功或者失败。

如何使用命令行cobra

首先,引入到库,在framework目录下创建cobra目录,将v1.2.1版本的源码放置进去,删去其中的go.mod和go.sum, 然后全文替换github.com/spf13.cobra为自己的项目地址。

为了让cmd命令执行时从参数command中获取到容器,进而从服务容器获取到服务实例,我们将服务容器嵌入到Command结构中,因此将服务器容器挂载到根Command上,所有子命令通过Root()方法获取。

最后,使用命令行后,http服务的启动也是通过command的命令执行的,为了从容器中获取gin.engine,需要将engine也作为一个服务注册到容器中。

【小结】:

  1. cobra逐层构建command,运行通过RuneE函数
  2. 将gin.Engine和上节的app目录结构,都作为服务提供者注入到服务容器中
http://www.lryc.cn/news/33128.html

相关文章:

  • eunomia-bpf 和 wasm-bpf 项目的 3 月进展
  • Spring框架核心功能手写实现
  • k8s-镜像构建Flink集群Native session
  • 在 k8S 中搭建 SonarQube 7.4.9 版本(使用 PostgreSQL 数据库)
  • 从getBean()分析BeanFactory和ApplicationContext
  • 详解Redis的主从同步原理
  • 前端项目上线后,浏览器缓存未刷新问题
  • Vulnhub系列:Raven 1
  • MybatisPlus------多数据源环境(十一)
  • Tomcat+IDEA+Servlet能显示页面但提交form表单出现404问题
  • 【蓝桥杯集训16】多源汇求最短路——Floyd算法(2 / 2)
  • simulink stateflow 状态机
  • 水库大坝安全监测的主要坝体类型介绍
  • 物理层概述(二)重点
  • 成都待慕电商:抖音极速版商品卡免佣扶持政策规则
  • 青岛双软认定标准
  • 【00后卷王秘籍】python自动化测试—Python自动化框架及工具
  • MySQL数据库基本操作
  • 2023年最新的站内SEO指南:如何通过关键词优化提高网站排名
  • 【Java】Java环开发环境安装
  • [蓝桥杯] 枚举、模拟和排列问题
  • C++基础了解-02-C++ 数据类型
  • 关于MSVCR100.dll、MSVCR100d.dll、Msvcp100.dll、abort()R6010等故障模块排查及解决方法
  • 【蓝桥杯集训·每日一题】AcWing 3305. 作物杂交
  • 深入浅出PaddlePaddle函数——paddle.to_tensor
  • JavaScript高级程序设计读书分享之10章——函数
  • 第八章 使用 ^%ZSTART 和 ^%ZSTOP 例程自定义启动和停止行为 - 设计注意事项
  • 工作实战之拦截器模式
  • 某美颜app sig参数分析
  • Linux - Linux系统优化思路