go cobra

Created

2024-10-28 13:33:18

Updated

2024-10-28 13:33:23

1 概念

Diagram
例子说明
# server 是 command(action),  'port' 是 一个flag,改变暴露的端口,对行为的修饰
# hugo 是 应用程序的名称
hugo server --port=1313
# git 是应用程序, clone 是command(action), URL 是Args, --bare是 flag
git clone URL --bare

2 实战

cobra github 文档 cobra-cli

# 安装cobra-cli 用于代码生成
go install github.com/spf13/cobra-cli@latest

mkdir my-app && cd my-app && cobra-cli init
# 或者
cobra-cli init my-app && cd my-app
tree
.
├── LICENSE
├── cmd
   └── root.go
├── go.mod
├── go.sum
└── main.go

2.1 根命令

cmd/root.go
--8<-- "go/.code/cobra/cmd/root.go"
go build .
./my-app -h

2.2 添加命令

# 接下来添加一个命令
cobra-cli add serve
# 会在 cmd目录下创建一个 serve.go 文件
cmd/serve.go 做相关修改
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>

*/
package cmd

import (
    "errors"
    "fmt"

    "github.com/spf13/cobra"
)

var serveCmd = &cobra.Command{
    Use:     "serve",                //  ./my-app -h 帮助信息显示的命令名
    Short:   "short serve",          //  ./my-app -h 会看到
    Long:    `A longer description`, //  ./my-app serve -h 会看到
    Aliases: []string{"s"},          //   命令别名 ./my-app s 等同于 ./my-app serve
    // 如果有错误, 就不要再显示 使用帮助了.
    // 默认没设置是 false , 命令执行有错误, 会显示帮助
    SilenceUsage: true,
    PersistentPreRun: func(cmd *cobra.Command, args []string) {
        fmt.Printf("serve PersistentPreRun run运行前 执行, 这个会被子命令继承,除非子命令自己写了自己的: %v\n", args)
    },
    PreRun: func(cmd *cobra.Command, args []string) {
        fmt.Printf("run 运行前执行, 不会被子命令继承: %v\n", args)
    },

    Run: func(cmd *cobra.Command, args []string) {
        fmt.Println("执行了 serve  子命令")
        // rootCmd 里设置的 全局config
        config := cmd.Flags().Lookup("config").Value
        // cmd.Flags() 包含所有的flag
        dirtyReload0 := cmd.Flags().Lookup("dirtyreload").Value
        // 获取 local flags
        dirtyReload := cmd.LocalFlags().Lookup("dirtyreload").Value
        fmt.Println(dirtyReload0, dirtyReload)
        // cmd.PersistentFlags()
        fmt.Println(config)
        // 参数
        fmt.Println("args:", args)
    },
    PostRun: func(cmd *cobra.Command, args []string) {
        fmt.Printf("run 运行后执行, 不会被子命令继承: %v\n", args)
    },
    PersistentPostRun: func(cmd *cobra.Command, args []string) {
        fmt.Printf("serve PersistentPostRun run运行后执行, 这个会被子命令继承,除非子命令自己写了自己的: %v\n", args)
    },
    // 如果不写这个 ,表示接收任意参数
    Args: func(cmd *cobra.Command, args []string) error {
        fmt.Println("所有 pre post run 之前执行")
        // 参数自定义验证
        if len(args) < 1 {
            return errors.New("至少一个参数")
        }
        fmt.Println("args:", args)
        // 返回nil 才会执行后续的run方法
        return nil
    },
}

func init() {
    rootCmd.AddCommand(serveCmd)
    serveCmd.Flags().Bool("dirtyreload", false, "Help message for dirty")
}
go build .
./my-app s
执行结果
执行了 serve  命令
false
~/.my-app.yaml
# 代码里 bool 类型的, 这里执行是 只要带上 就表示true
# 当然也可以 --dirtyreload=true
./my-app s --dirtyreload --config=./debug.yaml

2.3 命令添加子命令

给命令添加子命令
# 默认 没有-p 指明的话, 就是给rootCmd添加命令
cobra-cli add image -p 'serveCmd'
cmd/image.go
/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>

*/
package cmd

import (
    "fmt"

    "github.com/spf13/cobra"
)

// imageCmd represents the image command
var imageCmd = &cobra.Command{
    Use:   "image",
    Short: "image A brief ",
    Long:  `image A longer description.`,
    RunE: func(cmd *cobra.Command, args []string) error {
        fmt.Println("image called")
        // return errors.New("eeee")
        return nil

    },
    PersistentPostRun: func(cmd *cobra.Command, args []string) {
        fmt.Printf("image PersistentPostRun: %v\n", args)
    },
    // 用cobra 提供的方法, 之前我们在serve 命令中用的自定义
    Args: cobra.ExactArgs(1),

    /*
        这里的表示 只接收 这样的参数
        Args:      cobra.OnlyValidArgs,
        ValidArgs: []string{"abc", "efg"},
    */
}

func init() {
    serveCmd.AddCommand(imageCmd)
}
go build .
./my-app s image # 报错
./my-app s image abc
Back to top