从不看回复 發表於 2020-10-27 18:52:00

go cobra实例讲解

<h1 id="概述">概述</h1>
<p><code>cobra</code> 库是 golang 的一个开源第三方库,能够快速便捷的建立命令行应用程序。</p>
<p>优势:<code>cobra</code> 可以快速建立CLI程序,使我们更专注于命令需要处理的具体的业务逻辑。</p>
<p>举两个例子:</p>
<pre><code>hugo server --port=1313
git clone URL --bare
</code></pre>
<p>都是命令行程序。</p>
<h1 id="基本概念">基本概念</h1>
<p>cobra由三部分构成:<code>commands</code>,<code>arguments</code> 和 <code>flags</code></p>
<p><code>commands</code>:表示要执行的动作。每一个 <code>command</code> 表示应用程序的一个动作。每个命令可以包含子命令。</p>
<p><code>arguments</code>:给动作传入的参数。</p>
<p><code>flags</code>:表示动作的行为。可以设置执行动作的行为。<code>flags</code> 包括两种:对某个命令生效和对所有命令生效。</p>
<h1 id="安装方法">安装方法</h1>
<pre><code>go get -u github.com/spf13/cobra/cobra
</code></pre>
<p>github地址:https://github.com/spf13/cobra</p>
<h1 id="使用方法">使用方法</h1>
<h2 id="1创建cobra命令行应用程序">1.创建cobra命令行应用程序</h2>
<pre><code>cobra init code.byted.org/dfic/demo
</code></pre>
<p>在 <code>$GOPATH/src/code.byted.org.dfic/</code> 目录下创建一个名为 <code>demo</code> 的 <code>cobra</code> 命令行应用程序</p>
<p><code>main.go</code> 文件,完成初始化 <code>cobra</code> 功能。</p>
<p>第一次初始化可能会出现这个问题 <code>Error: required flag(s) "pkg-name" not set</code> 解决办法</p>
<pre><code>package main

import "code.byted.org/dfic/demo/cmd"

func main() {
    cmd.Execute()
}
</code></pre>
<h2 id="2添加命令">2.添加命令</h2>
<h3 id="21基本用法">2.1.基本用法</h3>
<p><code>cobra add version</code></p>
<p>cmd 文件夹下生成一个新的文件 version.go,定义这个新的命令的动作。</p>
<p>文件内容如下:</p>
<pre><code>import (
    "fmt"

    "github.com/spf13/cobra"
)

// versionCmd represents the version command
var versionCmd = &amp;cobra.Command{
    Use:   "version",
    Short: "A brief description of your command",
    Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

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.`,
    Run: func(cmd *cobra.Command, args []string) {
      fmt.Println("version called")
    },
}

func init() {
    rootCmd.AddCommand(versionCmd)

    // Here you will define your flags and configuration settings.

    // Cobra supports Persistent Flags which will work for this command
    // and all subcommands, e.g.:
    // versionCmd.PersistentFlags().String("foo", "", "A help for foo")

    // Cobra supports local flags which will only run when this command
    // is called directly, e.g.:
    // versionCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}
</code></pre>
<p>编译运行</p>
<pre><code>&gt; go build -o demo

&gt; ./demo -h

Usage:
demo

Available Commands:
help      Help about any command
version   A brief description of your command

Flags:
      --config string   config file (default is $HOME/.demo.yaml)
-h, --help            help for demo
-t, --toggle          Help message for toggle

执行新添加的命令
&gt; ./demo version
输出:version called
</code></pre>
<h3 id="22修改命令行为">2.2.修改命令行为</h3>
<p>将命令的行为添加到命令结构Run参数对应的方法中</p>
<pre><code>var versionCmd = &amp;cobra.Command{
    Use:   "version",
    Short: "A brief description of your command",
    Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

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.`,
    Run: func(cmd *cobra.Command, args []string) {
      fmt.Println("version called")
    },
}
</code></pre>
<h2 id="3添加flag">3.添加flag</h2>
<h3 id="31添加局部flag">3.1.添加局部flag</h3>
<p>在 version.go 文件的 <code>init</code> 函数中添加 <code>局部flag</code></p>
<pre><code>func init() {
    rootCmd.AddCommand(versionCmd)
    versionCmd.Flags().BoolP("test", "t", false, "test")
}
</code></pre>
<p>执行命令</p>
<pre><code>&gt; ./demo version -h

Usage:
demo version

Flags:
-h, --help   help for version
-t, --test   test

Global Flags:
      --config string   config file (default is $HOME/.demo.yaml)
</code></pre>
<h2 id="4-flag赋值">4. flag赋值</h2>
<p>如果需要使用 <code>全局flag</code> 或者 <code>局部flag</code>,需要在合适的作用域内定义变量存储 <code>flag</code> 值,以便 <code>flag</code> 可在特定作用域内生效。</p>
<h3 id="41使用全局flag">4.1.使用全局flag</h3>
<p>让一个 <code>flag</code> 对所有命令生效,需要在 root.go 文件中创建一个变量存储 <code>flag</code> 值。</p>
<p>如需要定义一个全局flag name:</p>
<pre><code>1.在root.go 文件中添加一个变量name

var name string

2.在init函数中添加全局flag,将flag值存储到变量name中

rootCmd.PersistentFlags().StringVar(&amp;name, "name", "", "set name")


3.在子命令version的Run方法中输出name
Run: func(cmd *cobra.Command, args []string) {
    fmt.Println("name is: ", name)
}


4.执行命令
./demo version --name wfl
输出:
name is:wfl
</code></pre>
<h3 id="42使用局部flag">4.2.使用局部flag</h3>
<p>让一个 <code>flag</code> 对某个命令生效,需要在该命令文件中创建一个变量存储 <code>flag</code> 值。</p>
<p>如需要给version命令定义一个局部flag name:</p>
<pre><code>1.定义变量sunsine
var sunshine string


2.在version.go的init函数中添加flag
versionCmd.Flags().StringVarP(&amp;sunshine, "sunshine", "s", "false", "you are my sunshine")


3.在子命令version.go的Run方法中输出
Run: func(cmd *cobra.Command, args []string) {
    fmt.Println("name is: ", name)
    fmt.Println("sunshine is: ", sunshine)
}


4.执行命令
./demo version --name wfl --sunshine wfl
输出:
name is:wfl
sunshine is:wfl
</code></pre>
<p><strong>问题:</strong></p>
<p>将 <code>flags</code> 存储到本地变量当中,那么其他命令是不是也可以用某个命令的 <code>局部flag</code> 呢?</p>
<p>答:不可以。局部flag虽然是定义在某个命令文件中作为局部变量,cmd 文件夹下的其他文件可以访问这个变量,但是其他命令如果没有定义自己的 <code>局部flag</code> 获取相同 <code>flag</code> 值的话,获取到的值是该局部变量的零值。</p>
<pre><code>1.添加一个新命令helloworld
&gt; cobra add helloworld


2.输出sunshine值
Run: func(cmd *cobra.Command, args []string) {
    fmt.Println("sunshine is: ", sunshine)
}


3.执行命令
&gt; ./demo helloworld --sunshine wfl
Error: unknown flag: --sunshine
输出错误未知flag。
原因就是该命令并未定义局部flagsunshine
</code></pre>
<h3 id="43必填flag">4.3.必填flag</h3>
<p>默认情况下,flag是optional(选填),若flag为必填,则需要做如下设置</p>
<p>如将version命令下的sunshine flag设置为必填</p>
<pre><code>1.init文件中增加flag定义
versionCmd.Flags().StringVarP(&amp;sunshine, "sunshine", "s", "", "you are my sunshine")
versionCmd.MarkFlagRequired("sunshine")

2.执行
&gt; ./demo version

3.输出
Error: required flag(s) "sunshine" not set
说明必须要设置flag sunshine

4.传入sunshineflag
&gt; ./demo version --sunshine wfl
输出: sunshine is:wfl
</code></pre>
<h2 id="5-嵌套子命令">5. 嵌套子命令</h2>
<p>cobra 的命令行工具可以创建嵌套子命令。使用 cobra add -p "父命令Cmd"。</p>
<p>比如</p>
<pre><code>1.给version命令添加一个子命令show
&gt; cobra add show -p "versionCmd"


2.在cobra生成的show.go文件的init方法中,自动将showCmd添加到versionCmd下作为子命令
func init() {
    versionCmd.AddCommand(showCmd)
}


3.执行嵌套子命令
&gt; ./demo version show
show called
</code></pre>
<h2 id="6-获取命令行参数值">6. 获取命令行参数值</h2>
<p><code>cobra</code> 常用的参数配置校验器如下:</p>
<pre><code>MinimumNArgs(int) 当参数数目低于配置的最小参数个数时报错
MaximumNArgs(int) 当参数数目大于配置的最大参数个数时报错
ExactArgs(int)    如果参数数目不是配置的参数个数时报错
NoArgs            没有参数则报错
</code></pre>
<p>类似 <code>git clone URL</code> 这种类型的命令行,URL 为传给 clone 命令的参数</p>
<p>获取URL的值,可以从 args 参数中直接取出</p>
<p>举例:</p>
<pre><code>1.添加一个命令path
&gt; cobra add path

2.设置该命令需要且仅需要一个参数,并在Run方法中取出参数
var pathCmd = &amp;cobra.Command{
    Use:   "path ",
    Short: "A brief description of your command",
    Long: `A longer description that spans multiple lines and likely contains examples
and usage of using your command. For example:

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.`,
    Args: cobra.ExactArgs(1),
    Run: func(cmd *cobra.Command, args []string) {
      fmt.Println("path called")
      fmt.Println("path:", args)
    },
}

3. 执行命令并输出
&gt; ./demo path /home
path: /home
</code></pre><br><br>
来源:https://www.cnblogs.com/niuben/p/13886555.html
頁: [1]
查看完整版本: go cobra实例讲解