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

news2025/8/7 16:59:23

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

第三方命令行工具库 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,那么所有的命令后面的参数都会是 arguments
        DisableFlagParsing bool

        // 是否打印自动生成字样: ("Auto generated by spf13/cobra...")
        DisableAutoGenTag bool

        // 是否显示[flags]字样
        DisableFlagsInUseLine bool

        // 是否打印建议
        DisableSuggestions bool

        // 两个字符串的差距多少会进入 suggest
        SuggestionsMinimumDistance int

        // 是否使用 Traverse 的方式来解析参数
        TraverseChildren bool

        // 解析错误白名单, 比如像未知参数
        FParseErrWhitelist FParseErrWhitelist
        
        // The *Run 函数运行顺序:
        //   * PersistentPreRun()
        //   * PreRun()
        //   * Run()
        //   * PostRun()
        //   * PersistentPostRun()
        // 会被继承的前置 Run
        PersistentPreRun func(cmd *Command, args []string)

        // 会被继承的前置 Run, 带 error
        PersistentPreRunE func(cmd *Command, args []string) error

        // 当前这个命令的前置 Run
        PreRun func(cmd *Command, args []string)
        // 当前这个命令的前置 Run,带 Error
        PreRunE 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)
        // 后置运行,带 error
        PostRunE func(cmd *Command, args []string) error
        // 会被继承的后置运行
        PersistentPostRun func(cmd *Command, args []string)
        // 会被继承的后置运行,带 error
        PersistentPostRunE 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.coloradmin.cn/o/394001.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

SpringBoot整合Mybatis详解

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录前言一、创建项目,导入依赖,完善项目结构二、编码1.yml配置2.编写实体类3.编写mapper.xml和接口4.编写业务层5.编写控制层6.启动类加上包扫描…

实践分享:Vue 项目如何迁移小程序

最近我们小组刚经历了将成熟的 HTML5 项目转换成小程序,并在app中运行的操作!记录下来分享给各位。 项目:将已有的 Vue 项目转为小程序, 在集成了FinClip SDK 的 App 中运行。 技术:uni-app、FinClip 两个注意事项&…

多机器人集群网络通信协议分析

本文讨论的是多机器人网络通信各层的情况和协议。 每个机器人连接一个数据传输通信模块(以下简称为数传,也泛指市面上的图传或图数一体的通信模块),数传之间进行组网来传递信息。 根据ISO的划分,网络通信的OSI模型分…

速看|快速软件开发框架突破信息孤岛,高效实现数字化发展!

在企业办公自动化发展的过程中,各部门之间的信息链接存在着链接不及时、信息孤岛的现象。伴随着日益激烈的市场竞争,这样单枪匹马的作战方式已经让不少企业吃尽了苦头,借助快速软件开发框架,可以有效打破信息孤岛,让各…

Jetpack Compose 中适配不同的屏幕尺寸

窗口大小分类 Compose 将 Android 设备的屏幕尺寸分为三类&#xff1a; Compact: 小屏幕&#xff0c;一般就是手机设备&#xff0c;屏幕宽度 < 600dpMedium&#xff1a;中等屏幕&#xff0c;大号的板砖手机如折叠屏或平板的竖屏&#xff0c;600dp < 屏幕宽度 < 840d…

swagger关闭/v2/api-docs仍然可以访问漏洞

今天接到安全团队的说swagger有未授权访问漏洞&#xff0c;即使在swagger关闭的情况下http://127.0.0.1:8086/agcloud/v2/api-docs?group%E7%94%A8%E6%88%B7%E5%85%B3%E8%81%94%E4%BF%A1%E6%81%AF%E6%A8%A1%E5%9D%97仍然还能访问。 看了下原来是有写一个拦截器 registry.addI…

图表控件TeeChart for .NET系列教程六:将数据添加到系列中(使用系列)

TeeChart for .NET是优秀的工业4.0 WinForm图表控件&#xff0c;官方独家授权汉化&#xff0c;集功能全面、性能稳定、价格实惠等优势于一体。TeeChart for .NET 中文版还可让您在使用和学习上没有任何语言障碍&#xff0c;至少可以节省30%的开发时间。 TeeChart for .NET最新…

BFD协议原理

BFD协议原理引入背景不使用BFD带来的问题OSPF感知慢VRRP产生次优路径BFD技术简介BFD会话建立方式和检测机制BFD会话建立过程BFD工作流程BFD的单臂回声BFD默认参数以及调整方法总结引入背景 随着网络应用的广泛部署&#xff0c;网络发生中断可能影响业务正常运行并造成重大损失…

Git开发常用指令及其使用场景

目录前言一、Git安装1.1 官网安装二、配置Git工具2.1 用户信息配置2.2 查看配置三、初始化仓库3.1 创建仓库四、常用命令4.1 git clone拉取远端仓库4.2 git分支操作4.2.1 查看分支4.2.2 分支操作4.3 撤回操作4.3.1 撤回删错的分支4.3.2 撤回提交4.3 拉取代码操作4.4 贮存操作五…

ChatGPT也有犯晕的时候

前面测试 ChatGPT 进行写代码、优化代码、解释代码、一般问答都表现的很好。偷个懒&#xff0c;用ChatGPT 帮我写段生物信息代码如果 ChatGPT 给出的的代码不太完善&#xff0c;如何请他一步步改好&#xff1f;代码看不懂&#xff1f;ChatGPT 帮你解释&#xff0c;详细到爆&…

详解Redis的主从同步原理

前言 Redis为了保证服务高可用&#xff0c;其中一种实现就是主从模式&#xff0c;即一个Redis服务端作为主节点&#xff0c;若干个Redis服务端作为主节点的从节点&#xff0c;从而实现即使某个服务端不可用时&#xff0c;也不会影响Redis服务的正常使用。本篇文章将对主从模式…

asp.net网站读取app.config配置内容

目录1、情况说明1.1 使用场景1.2 基本概念2、优化1、情况说明 1.1 使用场景 创建了一个网站&#xff08;项目A&#xff09;&#xff0c;又创建了一个访问数据的项目B。项目A因为是个网站&#xff0c;所有会有web.config文件。项目B是一个读取数据库的类库&#xff0c;会有一个…

小樽C++ 单章④ 字符数组与字符串

目录 一、字符与数组 1.求字符数组的长度 2.查找单词 二、字符串与数组 2.1 字符串倒序输出 2.2 字符串比较 2.3 大写字母输出 ​编辑 三、字符串常用函数 一、初始化字符串&#xff1a; 二、字符串操作&#xff1a;(增删改查) 三、截取与替换字符串 四、替换字符串…

从0开始学python -48

Python MySQL - mysql-connector 驱动 MySQL 是最流行的关系型数据库管理系统&#xff0c;如果你不熟悉 MySQL&#xff0c;可以先学习 MySQL 教程。 本章节我们为大家介绍使用 mysql-connector 来连接使用 MySQL&#xff0c; mysql-connector 是 MySQL 官方提供的驱动器。 我…

DoubleAccumulator 源码详解

DoubleAccumulator 简介 这个类是新增的并发统计工具&#xff0c;可以多线程安全计数。 他的构造方法有两个参数&#xff0c;分别是统计方法和初始值。所以具体的统计是加减乘除是由传入的操作方法决定的。 public DoubleAccumulator(DoubleBinaryOperator accumulatorFunct…

​力扣解法汇总1599. 经营摩天轮的最大利润

目录链接&#xff1a; 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目&#xff1a; https://github.com/September26/java-algorithms 原题链接&#xff1a;力扣 描述&#xff1a; 你正在经营一座摩天轮&#xff0c;该摩天轮共有 4 个座舱 &#xff0c;每个座舱…

Kubernetes调度之Pod亲和性

Kubernetes调度中的Pod亲和性abstract.pngPod亲和性节点亲和性&#xff0c;是基于节点的标签对Pod进行调度。而Pod亲和性则可以实现基于已经在节点上运行Pod的标签来约束新Pod可以调度到的节点。具体地&#xff0c;如果X上已经运行了一个或多个满足规则Y的Pod&#xff0c;则这个…

在ubuntu上(docker虚拟环境)部署完laravel的环境后如何运行一个基础的laravel项目

先测试laravel有没有安装成功 laravel如果报laravel command not found&#xff0c;先测试是否安装成功 find / -name laravel出现结果&#xff1a; 说明已经安装成功只是没有配环境变量 要么进这些文件夹测试那个路径下有真的laravel可执行文件&#xff0c;要么每个分别配置…

MCP2515国产替代DP2515带有SPI 接口的独立CAN 控制器

DP2515是一款独立控制器局域网络&#xff08;Controller AreaNetwork&#xff0c; CAN&#xff09;协议控制器&#xff0c;完全支持CAN V2.0B 技术规范。该器件能发送和接收标准和扩展数据帧以及远程帧。DP2515自带的两个验收屏蔽寄存器和六个验收滤波寄存器可以过滤掉不想要的…

图像处理--基于像素层面

python 图像锐化 图像锐化可以使图像的边缘更加清晰&#xff0c;增强图像的细节。常见的图像锐化算法有拉普拉斯算子、Sobel算子、Prewitt算子等。下面是使用拉普拉斯算子实现图像锐化的Python代码&#xff1a; import cv2 import numpy as npdef laplacian_sharpen(img, ksi…