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

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

第三方命令行工具库 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目录结构,都作为服务提供者注入到服务容器中
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值