ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

用 Cobra 构建现代化 Go CLI:命令树、Flag 与自动补全实战(以 CubeFS 为例)

用 Cobra 构建现代化 Go CLI:命令树、Flag 与自动补全实战(以 CubeFS 为例) 存储分布式文件系统对象存储云原生【免费下载链接】cubefscloud-native distributed storage项目地址https://gitcode.com/gh_mirrors/cu/cubefs点击查看免费下载Cobra 是 Go 生态中最流行的 CLI 框架之一它既是一个用于构建现代命令行应用的库也是一个可以自动生成应用骨架与命令文件的脚手架工具。本篇文章以 CubeFS 仓库内实际引入的 Cobra 源码vendored 于depends/spf13/cobra/对应 v1.2.1见 depends/Readme.md为主线完整讲解 Cobra 的命令、参数与 Flag 三大核心概念并结合 CubeFS 官方命令行工具cfs-cli入口在 cli/cli.go的源码实现展示这些机制在生产级分布式存储项目中的真实用法。读完本文你将能够独立搭建一个 Cobra 应用骨架、设计多级嵌套子命令、正确区分持久化 Flag 与局部 Flag、编写位置参数校验器、接入自动补全与文档生成并把 Cobra 的能力复用到自己的项目中。概览Cobra 是什么Cobra 是一个提供简单接口、用于创建强大现代 CLI 界面的库其交互风格与git、go等工具类似同时它也是一个可以快速生成 Cobra 应用脚手架的程序。Cobra 提供的能力包括基于子命令的 CLI如app server、app fetch完全 POSIX 兼容的 Flag同时支持短 Flag 与长 Flag嵌套子命令全局、局部与级联 Flag通过cobra init appname与cobra add cmdname快速生成应用与命令智能命令建议输入app srver时提示 did you meanapp server?为命令与 Flag 自动生成帮助信息自动识别-h、--help等帮助 Flag自动生成 bash 自动补全脚本自动生成 man 手册页命令别名Aliases让你在不破坏既有用法的情况下调整命令名灵活的自定义帮助、用法usage输出可选与 viper 的紧密集成用于构建 12-factor 应用Cobra 在众多 Go 大型项目中扮演着 CLI 层的中枢角色Kubernetes、Hugo、rkt、etcd、Moby前 Docker、Docker distribution、OpenShift、Delve、GopherJS、CockroachDB、Bleve、Istio、Linkerd、GitHub CLI 等均基于它构建。在 CubeFS 中Cobra 同样被用于实现集群管理命令行的整套命令树。核心概念命令、参数与 FlagCobra 建立在命令Commands、参数Args与 Flag 三者的结构之上Commands代表动作Args代表事物Flags是对这些动作的修饰。最佳实践是让应用的使用方式读起来像一句自然语言用户凭直觉就能掌握用法。推荐遵循的模式是APPNAME VERB NOUN --ADJECTIVE或APPNAME COMMAND ARG --FLAG几个现实示例可以更直观地说明这一点。下面的命令中server是命令port是 Flaghugo server --port1313下面的命令中我们在让 Git 以 bare 方式克隆某个 URLgit clone URL --bareCommands命令是应用的中枢Command 是应用的中枢点。应用支持的每一次交互都包含在一个 Command 中一个命令可以拥有子命令也可以选择性地运行某个动作Run。上面示例中的server就是一个命令。在 CubeFS 的cfs-cli中根命令CFSCmd在 cli/cmd/root.go 中构建它通过AddCommand一次性挂载了 cluster、volume、user、metanode、datanode、datapartition、metapartition、config、zone、nodeset、acl、uid、quota、disk、version、flashnode、flashgroup、balance 等十多个一级子命令而 volume 命令又在 cli/cmd/vol.go 中继续挂载了 list、create、expand、shrink、update、info、delete 等二级子命令。这就是典型的“多级嵌套子命令”形态cfs-cli volume create vol1 user1。Flags修饰命令行为Flag 是修饰命令行为的一种方式。Cobra 既支持完全 POSIX 兼容的 Flag也兼容 Go 标准库的 flag package。Cobra 命令可以定义两种 Flag会传递到子命令的持久化 Flag仅对当前命令可用的局部 Flag。Flag 功能由 pflag 正是通过flag github.com/cubefs/cubefs/depends/spf13/pflag引入 pflag 的。安装使用 Cobra 的第一步是用go get安装最新版本的库。下面这条命令会同时安装cobra生成器可执行文件、库本身及其依赖go get -u github.com/spf13/cobra/cobra然后在你的应用中引入 Cobraimport github.com/spf13/cobra在 CubeFS 中Cobra 是作为 vendor 依赖直接存放在仓库内的depends/spf13/cobra/所有引入处都写为github.com/cubefs/cubefs/depends/spf13/cobra这样的仓库内路径这保证了构建不依赖外部网络。快速开始虽然你可以自由设计自己的组织方式但典型的 Cobra 应用通常遵循以下目录结构▾ appName/ ▾ cmd/ add.go your.go commands.go here.go main.go在 Cobra 应用中main.go通常非常精简它只做一件事初始化 Cobra。package main import ( {pathToYourApp}/cmd ) func main() { cmd.Execute() }CubeFS 的 cli/cli.go 也遵循这一模式main()先初始化日志随后调用runCLI()其中通过cmd.LoadConfig()加载配置、setupCommands(cfg)组装命令树、最终执行cfsCli.Execute()。使用 Cobra 生成器Cobra 提供了自己的程序来创建应用并添加你想要的任何命令这是把 Cobra 集成进应用最省事的方式。编译生成器后cobra init [app]会为你创建初始应用代码它会自动将指定的许可证应用到你的应用。cobra init既可以在当前应用目录运行也可以指定一个相对路径指向已有项目如果目录不存在会被自动创建。由于生成器已从 GOPATH 解耦--pkg-name现在是必填参数mkdir -p newApp cd newApp cobra init --pkg-name github.com/spf13/newApp或cobra init --pkg-name github.com/spf13/newApp path/to/newApp应用初始化之后cobra add可以继续帮你创建子命令。比如你想要以下命令结构app serveapp configapp config create在项目目录main.go 所在位置执行cobra add serve cobra add config cobra add create -p configCmd注意命令名必须使用 camelCase不要用 snake_case 或 snake-case否则会遇到错误。例如cobra add add-user是不对的cobra add addUser才是合法的。执行完这三条命令后应用结构大致如下▾ app/ ▾ cmd/ serve.go config.go create.go main.go此时运行go run main.go、go run main.go serve、go run main.go config、go run main.go config create以及go run main.go help serve等都已可用。生成器还支持通过~/.cobra.yaml配置文件避免重复输入公共信息author: Steve Francia spfspf13.com license: MIT将license设为none表示不指定许可证也可以自定义许可证文本内置许可证包括 GPLv2、GPLv3、LGPL、AGPL、MIT、2-Clause BSD、3-Clause BSD 等。使用 Cobra 库手动实现创建 rootCmdCobra 不需要任何特殊构造函数直接创建命令即可。通常把它放在app/cmd/root.govar rootCmd cobra.Command{ Use: hugo, Short: Hugo is a very fast static site generator, Long: A Fast and Flexible Static Site Generator built with love by spf13 and friends in Go. Complete documentation is available at http://hugo.spf13.com, Run: func(cmd *cobra.Command, args []string) { // Do Stuff Here }, } func Execute() { if err : rootCmd.Execute(); err ! nil { fmt.Println(err) os.Exit(1) } }通常你会在init()函数中定义 Flag 并处理配置。例如cmd/root.gopackage cmd import ( fmt os homedir github.com/mitchellh/go-homedir github.com/spf13/cobra github.com/spf13/viper ) var ( // Used for flags. cfgFile string userLicense string rootCmd cobra.Command{ Use: cobra, Short: A generator for Cobra based Applications, Long: Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application., } ) // Execute executes the root command. func Execute() error { return rootCmd.Execute() } func init() { cobra.OnInitialize(initConfig) rootCmd.PersistentFlags().StringVar(cfgFile, config, , config file (default is $HOME/.cobra.yaml)) rootCmd.PersistentFlags().StringP(author, a, YOUR NAME, author name for copyright attribution) rootCmd.PersistentFlags().StringVarP(userLicense, license, l, , name of license for the project) rootCmd.PersistentFlags().Bool(viper, true, use Viper for configuration) viper.BindPFlag(author, rootCmd.PersistentFlags().Lookup(author)) viper.BindPFlag(useViper, rootCmd.PersistentFlags().Lookup(viper)) viper.SetDefault(author, NAME HERE EMAIL ADDRESS) viper.SetDefault(license, apache) rootCmd.AddCommand(addCmd) rootCmd.AddCommand(initCmd) } func er(msg interface{}) { fmt.Println(Error:, msg) os.Exit(1) } func initConfig() { if cfgFile ! { // Use config file from the flag. viper.SetConfigFile(cfgFile) } else { // Find home directory. home, err : homedir.Dir() if err ! nil { er(err) } // Search config in home directory with name .cobra (without extension). viper.AddConfigPath(home) viper.SetConfigName(.cobra) } viper.AutomaticEnv() if err : viper.ReadInConfig(); err nil { fmt.Println(Using config file:, viper.ConfigFileUsed()) } }对照 CubeFS 的 cli/cmd/root.go你会发现同样的骨架cobra.Command定义根命令Flags()注册--version布尔 FlagAddCommand挂载子命令还通过SuggestionsFor(args[0])在未知命令时给出建议并设置SilenceErrors、SilenceUsage控制错误输出。创建 main.go有了根命令还需要在 main 函数中执行它。Execute应当运行在根命令上以保证清晰虽然它也可以被调用在任意命令上。package main import ( {pathToYourApp}/cmd ) func main() { cmd.Execute() }创建更多命令额外的命令通常每个放在cmd/目录下的独立文件中。如果要创建一个 version 命令可以创建cmd/version.go并填充如下内容package cmd import ( fmt github.com/spf13/cobra ) func init() { rootCmd.AddCommand(versionCmd) } var versionCmd cobra.Command{ Use: version, Short: Print the version number of Hugo, Long: All software has versions. This is Hugos, Run: func(cmd *cobra.Command, args []string) { fmt.Println(Hugo Static Site Generator v0.9 -- HEAD) }, }CubeFS 的 cli/cmd/version.go 展示了真实项目中“命令即子命令树”的写法version命令下又挂载了 create、del、list、setStrategy 四个子命令并配置了Aliases别名与cobra.MinimumNArgs(0)参数校验。使用 FlagFlag 提供修饰符来控制动作命令的运行方式。将 Flag 赋给命令由于 Flag 的定义和使用位置不同需要用一个作用域正确的变量来承载var Verbose bool var Source string有两种不同的赋值方式。持久化 FlagPersistent Flags持久化 Flag 意味着该 Flag 对它所挂载的命令以及该命令之下的所有子命令都可用。全局 Flag 就把 Flag 作为持久化 Flag 挂在根命令上rootCmd.PersistentFlags().BoolVarP(Verbose, verbose, v, false, verbose output)局部 FlagLocal Flags局部 Flag 只作用于挂载它的那一个命令localCmd.Flags().StringVarP(Source, source, s, , Source directory to read from)父命令上的局部 Flag默认情况下Cobra 只解析目标命令上的局部 Flag父命令上的局部 Flag 会被忽略。启用Command.TraverseChildren后Cobra 会在执行目标命令之前解析每条命令上的局部 Flagcommand : cobra.Command{ Use: print [OPTIONS] [COMMANDS], TraverseChildren: true, }将 Flag 与配置绑定你也可以把 Flag 与 viper 绑定var author string func init() { rootCmd.PersistentFlags().StringVar(author, author, YOUR NAME, Author name for copyright attribution) viper.BindPFlag(author, rootCmd.PersistentFlags().Lookup(author)) }这个示例把持久化 Flagauthor与 viper 绑定。注意当用户没有提供--authorFlag 时变量author不会被赋为配置文件中的值。必填 FlagFlag 默认是可选的。如果你希望在某个 Flag 未设置时命令报错把它标记为必填即可rootCmd.Flags().StringVarP(Region, region, r, , AWS region (required)) rootCmd.MarkFlagRequired(region)在 CubeFS 的cfs-cli中config set子命令cli/cmd/config.go在Run内对masterAddr与timeout做了非空与取值范围校验timeout 必须小于math.MaxUint16且不能为 0体现了“Flag 解析 运行时校验”配合的典型模式。位置参数与自定义参数校验位置参数的校验可以通过Command的Args字段指定。内置的校验器如下NoArgs—— 存在任何位置参数时报错ArbitraryArgs—— 接受任意参数OnlyValidArgs—— 存在不在Command.ValidArgs字段中的位置参数时报错MinimumNArgs(int)—— 位置参数少于 N 个时报错MaximumNArgs(int)—— 位置参数多于 N 个时报错ExactArgs(int)—— 位置参数不是恰好 N 个时报错ExactValidArgs(int)—— 位置参数不是恰好 N 个或存在不在ValidArgs中的参数时报错RangeArgs(min, max)—— 参数个数不在 min 与 max 之间时报错。设置自定义校验器的示例var cmd cobra.Command{ Short: hello, Args: func(cmd *cobra.Command, args []string) error { if len(args) 1 { return errors.New(requires a color argument) } if myapp.IsValidColor(args[0]) { return nil } return fmt.Errorf(invalid color specified: %s, args[0]) }, Run: func(cmd *cobra.Command, args []string) { fmt.Println(Hello, World!) }, }从源码看这些内置校验器实现在 args.go 中NoArgs、ArbitraryArgs、OnlyValidArgs是函数而MinimumNArgs、MaximumNArgs、ExactArgs、ExactValidArgs、RangeArgs是返回PositionalArgs的闭包工厂函数统一类型为func(cmd *Command, args []string) errorargs.go。CubeFS 的cfs-cli大量使用了cobra.MinimumNArgs(0)见 cli/cmd/vol.go 与 cli/cmd/root.go用于允许不带额外参数地打印帮助。完整示例三层命令树下面的示例定义了三个命令两个在顶层一个cmdTimes是其中一个顶层命令的子命令。这个例子中根命令不可执行没有给 rootCmd 提供Run因此必须提供子命令。同时只为单个命令定义了一个 Flagpackage main import ( fmt strings github.com/spf13/cobra ) func main() { var echoTimes int var cmdPrint cobra.Command{ Use: print [string to print], Short: Print anything to the screen, Long: print is for printing anything back to the screen. For many years people have printed back to the screen., Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { fmt.Println(Print: strings.Join(args, )) }, } var cmdEcho cobra.Command{ Use: echo [string to echo], Short: Echo anything to the screen, Long: echo is for echoing anything back. Echo works a lot like print, except it has a child command., Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { fmt.Println(Echo: strings.Join(args, )) }, } var cmdTimes cobra.Command{ Use: times [string to echo], Short: Echo anything to the screen more times, Long: echo things multiple times back to the user by providing a count and a string., Args: cobra.MinimumNArgs(1), Run: func(cmd *cobra.Command, args []string) { for i : 0; i echoTimes; i { fmt.Println(Echo: strings.Join(args, )) } }, } cmdTimes.Flags().IntVarP(echoTimes, times, t, 1, times to echo the input) var rootCmd cobra.Command{Use: app} rootCmd.AddCommand(cmdPrint, cmdEcho) cmdEcho.AddCommand(cmdTimes) rootCmd.Execute() }这个例子中的关键点cmdTimes.Flags().IntVarP通过-t/--times短长 Flag 绑定echoTimes变量默认值为 1rootCmd.AddCommand(cmdPrint, cmdEcho)挂载顶层命令cmdEcho.AddCommand(cmdTimes)实现嵌套。这与 CubeFScfs-cli中rootCmd.AddCommand(newVolCmd(client), ...)、cmd.AddCommand(newVolListCmd(client), ...)的多级挂载方式cli/cmd/root.go、cli/cmd/vol.go完全同构。帮助命令Help Command当你的应用拥有子命令时Cobra 会自动添加一个 help 命令。用户运行app help时会触发它同时 help 也支持所有其他命令作为输入。例如你有一个叫create的命令且没有额外配置app help create也能正常工作。每个命令都会自动拥有--helpFlag。示例下面这段输出完全由 Cobra 自动生成除了命令与 Flag 的定义外不需要任何额外代码$ cobra help Cobra is a CLI library for Go that empowers applications. This application is a tool to generate the needed files to quickly create a Cobra application. Usage: cobra [command] Available Commands: add Add a command to a Cobra Application help Help about any command init Initialize a Cobra Application Flags: -a, --author string author name for copyright attribution (default YOUR NAME) --config string config file (default is $HOME/.cobra.yaml) -h, --help help for cobra -l, --license string name of license for the project --viper use Viper for configuration (default true) Use cobra [command] --help for more information about a command.Help 本身就是一个普通命令没有任何特殊逻辑。事实上你也可以提供自己的 help 实现。自定义 help你可以通过以下函数提供自己的 Help 命令或为默认命令提供自定义模板cmd.SetHelpCommand(cmd *Command) cmd.SetHelpFunc(f func(*Command, []string)) cmd.SetHelpTemplate(s string)后两者同样会应用到所有子命令。用法消息Usage Message当用户提供了非法的 Flag 或非法命令时Cobra 会向用户展示 usage。示例你可能已经在上面的帮助输出中见过它了——因为默认的 help 把 usage 内嵌在了输出中$ cobra --invalid Error: unknown flag: --invalid Usage: cobra [command] Available Commands: add Add a command to a Cobra Application help Help about any command init Initialize a Cobra Application Flags: -a, --author string author name for copyright attribution (default YOUR NAME) --config string config file (default is $HOME/.cobra.yaml) -h, --help help for cobra -l, --license string name of license for the project --viper use Viper for configuration (default true) Use cobra [command] --help for more information about a command.自定义 usage你可以提供自己的 usage 函数或模板。和 help 一样函数与模板都通过公开方法覆盖cmd.SetUsageFunc(f func(*Command) error) cmd.SetUsageTemplate(s string)版本 FlagVersion Flag如果根命令上设置了Version字段Cobra 会自动添加一个顶层的--versionFlag。带--version运行应用会按照版本模板把版本打印到 stdout。模板可以通过cmd.SetVersionTemplate(s string)函数自定义。CubeFS 的cfs-cli对版本的处理体现了这一机制cli/cmd/root.go在根命令的Run中检测--versionFlag通过BoolVarP(optShowVersion, version, v, ...)注册命中时调用proto.DumpVersion(CLI)打印版本信息。PreRun 与 PostRun 钩子在命令的主Run函数之前或之后运行函数是可行的。PersistentPreRun和PreRun会在Run之前执行PersistentPostRun和PostRun在Run之后执行。Persistent*Run函数会被子命令继承除非子命令声明了自己的版本。这些函数的执行顺序是PersistentPreRunPreRunRunPostRunPersistentPostRun下面是一个两个命令都使用了全部钩子的示例。当子命令执行时它会运行根命令的PersistentPreRun但不会运行根命令的PersistentPostRunpackage main import ( fmt github.com/spf13/cobra ) func main() { var rootCmd cobra.Command{ Use: root [sub], Short: My root command, PersistentPreRun: func(cmd *cobra.Command, args []string) { fmt.Printf(Inside rootCmd PersistentPreRun with args: %v\n, args) }, PreRun: func(cmd *cobra.Command, args []string) { fmt.Printf(Inside rootCmd PreRun with args: %v\n, args) }, Run: func(cmd *cobra.Command, args []string) { fmt.Printf(Inside rootCmd Run with args: %v\n, args) }, PostRun: func(cmd *cobra.Command, args []string) { fmt.Printf(Inside rootCmd PostRun with args: %v\n, args) }, PersistentPostRun: func(cmd *cobra.Command, args []string) { fmt.Printf(Inside rootCmd PersistentPostRun with args: %v\n, args) }, } var subCmd cobra.Command{ Use: sub [no options!], Short: My subcommand, PreRun: func(cmd *cobra.Command, args []string) { fmt.Printf(Inside subCmd PreRun with args: %v\n, args) }, Run: func(cmd *cobra.Command, args []string) { fmt.Printf(Inside subCmd Run with args: %v\n, args) }, PostRun: func(cmd *cobra.Command, args []string) { fmt.Printf(Inside subCmd PostRun with args: %v\n, args) }, PersistentPostRun: func(cmd *cobra.Command, args []string) { fmt.Printf(Inside subCmd PersistentPostRun with args: %v\n, args) }, } rootCmd.AddCommand(subCmd) rootCmd.SetArgs([]string{}) rootCmd.Execute() fmt.Println() rootCmd.SetArgs([]string{sub, arg1, arg2}) rootCmd.Execute() }输出Inside rootCmd PersistentPreRun with args: [] Inside rootCmd PreRun with args: [] Inside rootCmd Run with args: [] Inside rootCmd PostRun with args: [] Inside rootCmd PersistentPostRun with args: [] Inside rootCmd PersistentPreRun with args: [arg1 arg2] Inside subCmd PreRun with args: [arg1 arg2] Inside subCmd Run with args: [arg1 arg2] Inside subCmd PostRun with args: [arg1 arg2] Inside subCmd PersistentPostRun with args: [arg1 arg2]观察输出可以印证继承规则执行sub时subCmd没有声明PersistentPreRun于是继承了根命令的PersistentPreRun而它声明了自己的PersistentPostRun因此根命令的PersistentPostRun不再执行。这些*Run字段的定义与执行顺序在 command.go 的注释中有明确约定。未知命令时的智能建议当发生 unknown command 错误时Cobra 会自动打印建议。这让 Cobra 在用户拼写错误时的表现与git命令类似。例如$ hugo srever Error: unknown command srever for hugo Did you mean this? server Run hugo --help for usage.建议基于所有已注册子命令自动生成并使用 Levenshtein 距离的实现。所有与命令距离不超过 2忽略大小写的已注册命令都会被展示为建议。如果你需要禁用建议或调整字符串距离可以使用command.DisableSuggestions true或command.SuggestionsMinimumDistance 1你也可以通过SuggestFor属性显式指定某个命令在哪些名字下被建议。这对于那些与字符串距离无关、但在你的命令集合语境下合理的建议非常有用也可以用于你不想设置别名的情况。例如$ kubectl remove Error: unknown command remove for kubectl Did you mean this? delete Run kubectl help for usage.CubeFS 的根命令同样利用了这套机制在 cli/cmd/root.go 中遇到未知命令时调用cmd.SuggestionsFor(args[0])收集建议并拼装出 Did you mean this? 提示后以cfs-cli: unknown command的形式输出错误。为命令生成文档Cobra 可以基于子命令、Flag 等生成多种格式的文档MarkdownReStructured TextMan Page以 Markdown 为例doc/md_docs.md 展示了生成整棵命令树文档的方法用doc.GenMarkdownTree(cmd, ./)可以为命令树中每个命令生成一个独立的 Markdown 文件而GenMarkdown则用于只生成单个命令的文档。生成 bash 自动补全Cobra 可以生成 bash-completion 文件。如果你为命令补充更多信息这些补全可以变得非常强大和灵活。具体可阅读 Bash Completions。CubeFS 的cfs-cli就内置了补全生成命令在 cli/cli.go 中setupCommands向根命令添加了一个自定义的completion子命令调用cfsRootCmd.CFSCmd.GenBashCompletionFile(cfs-cli.sh)在本地生成cfs-cli.sh并在提示中给出安装指引将source语句写入~/.bashrc后重新加载。这正是 README 所述 “automatically generated bash autocomplete” 在生产 CLI 中的落地方式。生成 zsh 自动补全Cobra 同样可以生成 zsh-completion 文件。详见 Zsh Completions。除 bash 与 zsh 外仓库内还包含 fish 与 powershell 的补全实现fish_completions.md、powershell_completions.md补全逻辑统一收敛在 shell_completions.go 中。许可证Cobra 以 Apache 2.0 许可证发布见 LICENSE.txt。CubeFS 将其 vendored 进仓库作为直接依赖使用见 depends/Readme.md因此引入该框架不会给项目的许可证合规带来额外负担。小结在 CubeFS 中观察 Cobra 的最佳实践通过本文可以总结出 Cobra 在真实生产项目如 CubeFS 的cfs-cli中的几条最佳实践main.go 保持精简只做初始化与Execute()cli/cli.go命令树集中挂载根命令在NewRootCmd中一次性AddCommand所有一级子命令各子命令再自行扩展二级/三级命令cli/cmd/root.go合理使用 Args 校验与别名用cobra.MinimumNArgs(0)放宽参数约束、用Aliases提供便捷简称cli/cmd/vol.go利用智能建议与错误控制SuggestionsForSilenceErrors/SilenceUsage让 CLI 对用户更友好cli/cmd/root.go内置补全生成命令把GenBashCompletionFile暴露为 CLI 子命令运维人员一条命令即可启用 Tab 补全cli/cli.go。无论你是要为自己的存储系统、数据库驱动还是内部工具编写 CLICobra 提供的命令树、POSIX Flag、参数校验、帮助/usage 自动生成、智能建议、文档与补全生成这整套能力都能让你以极小的样板代码获得与主流云原生工具一致的交互体验。赞分享存储分布式文件系统对象存储云原生【免费下载链接】cubefscloud-native distributed storage项目地址https://gitcode.com/gh_mirrors/cu/cubefs点击查看免费下载相关推荐基于 Cobra 构建现代化 Go CLI以 k3sup 的命令行实现为实战范例基于 Cobra 构建现代化 Go CLI以 k3sup 的命令行实现为实战范例 Cobra 是 Go 生态中最流行的命令行应用开发库用于构建类似 git、云原生运维CLIFlipper Zero Unleashed 固件 MIFARE Ultralight AESMF0AES20全功能硬件验证方案从身份识别到安全消息的端到端 QA 指南Flipper Zero Unleashed 固件 MIFARE Ultralight AESMF0AES20全功能硬件验证方案从身份识别到安全消息的端到人工智能AI AgentAgent 沙箱云原生容器运行时零信任在 vcluster 中实战 Cobra构建现代 Go CLI 的命令、参数与标志体系在 vcluster 中实战 Cobra构建现代 Go CLI 的命令、参数与标志体系 Cobra 是 Go 生态中最流行的 CLI 开发库提供子命令体系、云原生集群管理虚拟化多集群上一篇Lightdash 授权体系与权限模型深度解析CASL Ability、双层角色叠加与自定义作用域下一篇Schema DescriptorsSanity 模式的可序列化描述语言与同步协议解析创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表