第15节 Cobra

❤️💕💕Go语言高级篇章,在此之前建议您先了解基础和进阶篇。Myblog:http://nsddd.topopen in new window

Go语言基础篇open in new window

Go语言100篇进阶open in new window


[TOC]

cobra 简介

提示

  • cobra 是一个用于生成命令行工具的框架 (本身也是一个命令行工具)
  • 非常简单,易用
  • 使用它的项目很多 (kubernetes、etcd、hugo、docker……)

开源地址:https://github.com/spf13/cobra

Cobra 安装

  • -u :update
go get -u github.com/spf13/cobra@latest

项目中导入

import "github.com/spf13/cobra"

cobra-cli

cobra-cli是一个命令行程序,用于生成 Cobra 应用程序和命令文件。它将引导您的应用程序脚手架以快速开发基于 Cobra 的应用程序。这是将 Cobra 合并到您的应用程序中的最简单方法。

它可以通过运行来安装:

go install github.com/spf13/cobra-cli@latest

cobra 项目创建

建议使用Go Module 模式,首先,创建一个Go Module项目,名称采用 clid

mkdir clid; cd clid 
go mod init clid

一般使用上面的方法有点麻烦,那么可以帮助你生成开源协议和一些东西:

cobra init clid  -a xiongxinwei -l MIT 

📜 对上面的解释

编译

我们创建完之后是可以直接用 go build 编译项目的:

编译信息展开
PS D:clid> go build
PS D:clid> ls

    Directory: D:clid

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d----          2022/11/15     9:32                cmd
-a---          2022/11/15     9:49        4336640 clid.exe
-a---          2022/11/15     9:04            177 go.mod
-a---          2022/11/15     9:04            896 go.sum
-a---          2022/11/15     9:32          11358 LICENSE
-a---          2022/11/15     9:49            622 main.go

PS D:clid> .\clid.exe
A longer description that spans multiple lines and likely contains
examples and usage of using your application. 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.

main.go

我们观察main.go

/*
Copyright © 2022 xiongxinwei

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package main

import "go-advancend-code/cobra/cmd"

func main() {
	cmd.Execute()
}

很简单的一个函数,就只有 cmd.Execute()

Execute将所有子命令添加到根命令并适当设置标志。它由main.main()调用。它只需要在rootCmd上发生一次。

那么我们可以去看 root.go文件了

root.go

cmd/root.go 目录:

这个目录是会影响到项目的协议的~

/*
Copyright © 2022 xiongxinwei

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package cmd

import (
	"os"

	"github.com/spf13/cobra"
)



// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:   "cobra",
	Short: "A brief description of your application",
	Long: 
    `A longer description that spans multiple lines and likely contains
examples and usage of using your application. 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.`,
	// Uncomment the following line if your bare application
	// has an action associated with it:
	// Run: func(cmd *cobra.Command, args []string) { },
}

// Execute adds all child commands to the root command and sets flags appropriately.
// This is called by main.main(). It only needs to happen once to the rootCmd.
func Execute() {
	err := rootCmd.Execute()
	if err != nil {
		os.Exit(1)
	}
}

func init() {
	// Here you will define your flags and configuration settings.
	// Cobra supports persistent flags, which, if defined here,
	// will be global for your application.

	// rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.cobra.yaml)")

	// Cobra also supports local flags, which will only run
	// when this action is called directly.
	rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

提示

我们可以看到上面有 runshortLong

是的,我们可以修改这些信息来调整输出信息

修改 long

var rootCmd = &cobra.Command{
	Use:   "cobra",
	Short: "A brief description of your application",
	Long:  `一个帮助信息`,
}

🚀 编译结果如下:

PS D:clid> go run .\main.go
一个帮助信息

为命令加上一个子命令

添加一个名叫 test 的子命令

cobra add test -a xiongxinwei -l MIT

效果 可以看出来 cmd目录下多了一个 test.go

PS D:clid> pwd

Path
----
D:clid

PS D:clid> ls cmd

    Directory: D:clid\cmd

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2022/11/15     9:52           1973 root.go

PS D:clid> cobra add test
test created at D:clid
PS D:clid> ls cmd       

    Directory: D:clid\cmd

Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
-a---          2022/11/15     9:52           1973 root.go
-a---          2022/11/15     9:58           1064 test.go

修改基本信息运行:

// testCmd represents the test command
var testCmd = &cobra.Command{
	Use:   "测试use",
	Short: "测试short",
	Long:  `测试long信息`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("测试run")
	},
}

🚀 编译结果如下:

PS D:clid> go run .\main.go
一个帮助信息

Usage:
  cobra [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  help        Help about any command
  测试use       测试short

Flags:
  -h, --help     help for cobra
  -t, --toggle   Help message for toggle

Use "cobra [command] --help" for more information about a command.

尝试:

.\clid.exe 测试use
测试run

再一次尝试:

PS D:clid> .\clid.exe 测试use -h
测试long信息

Usage:
  cobra 测试use [flags]

Flags:
  -h, --help   help for 测试use

so

所以我们突然明白了,原来这个命令主要是基于 主命令 root.go 下面的,root.go 就是 cobra

我们就可以基于此设置一系列子命令

绑定父命令

每个子命令都有一个 init 函数,就是用来绑定的~

func init() {
	rootCmd.AddCommand(testCmd)
}

创建一个 version 命令

cobra add version -a xiongxinwei -l MIT

修改:

/*
Copyright © 2022 xiongxinwei

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// versionCmd represents the version command
var versionCmd = &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)

	testCmd.AddCommand(versionCmd)

}

🚀 编译结果如下:

PS D:clid> go build               
PS D:clid> .\clid.exe test  
测试run
PS D:clid> .\clid.exe version
Error: unknown command "version" for "cobra"
Run 'cobra --help' for usage.
PS D:clid> .\clid.exe test version
version called

可以看到绑定到 test 上面了,当然你可以取消注释,同时绑定两个~

PS D:\文档\最近的\awesome-golang\docs\go-advancend\code\cobra\clid> .\clid.exe test version
version called
PS D:\文档\最近的\awesome-golang\docs\go-advancend\code\cobra\clid> .\clid.exe version
version called
PS D:\文档\最近的\awesome-golang\docs\go-advancend\code\cobra\clid> .\clid.exe test
测试run

为命令添加选项

这个我们就需要去 init() 函数中添加方法了:

/*
Copyright © 2022 xiongxinwei

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package cmd

import (
	"fmt"

	"github.com/spf13/cobra"
)

// versionCmd represents the version command
var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "关于版本信息短描述",
	Long:  `关于版本信息长描述`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("version called")
		author, _ := cmd.Flags().GetString("author")
		fmt.Println("作者是:", author)

	},
}

func init() {
	rootCmd.AddCommand(versionCmd)

	testCmd.AddCommand(versionCmd)

	// 添加参数
	versionCmd.Flags().StringP("author", "n", "default", "name") //名称,简写,默认值,描述

}

🚀 编译结果如下:

PS D:\文档\最近的\awesome-golang\docs\go-advancend\code\cobra\clid> go build
PS D:\文档\最近的\awesome-golang\docs\go-advancend\code\cobra\clid> .\clid.exe version -help
Error: unknown shorthand flag: 'e' in -elp
Usage:
  cobra test version [flags]

Flags:
  -n, --author string   name (default "default")
  -h, --help            help for version

PS D:\文档\最近的\awesome-golang\docs\go-advancend\code\cobra\clid> .\clid.exe version
version called
作者是: default
PS D:\文档\最近的\awesome-golang\docs\go-advancend\code\cobra\clid> .\clid.exe test version
version called
作者是: default
PS D:\文档\最近的\awesome-golang\docs\go-advancend\code\cobra\clid> .\clid.exe test -h     
测试long信息

Usage:
  cobra test [flags]
  cobra test [command]

Available Commands:
  version     关于版本信息短描述

Flags:
  -h, --help   help for test

Use "cobra test [command] --help" for more information about a command.

指定参数:

PS D:\文档\最近的\awesome-golang\docs\go-advancend\code\cobra\clid> .\clid.exe  version -n 王艺桦     
version called
作者是: 王艺桦

补充 run参数的匿名函数

// versionCmd represents the version command
var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "关于版本信息短描述",
	Long:  `关于版本信息长描述`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("version called")
		author, _ := cmd.Flags().GetString("author")
		fmt.Println("作者是:", author)

	},
}
  • cmd 是一个指针,可以通过cmd来获取参数
  • args 是一个数组,可以通过args来获取参数

💡简单的一个案例如下:

/*
Copyright © 2022 xiongxinwei

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
*/
package cmd

import (
	"fmt"
	"strconv"

	"github.com/spf13/cobra"
)

// versionCmd represents the version command
var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "关于版本信息短描述",
	Long:  `关于版本信息长描述`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("version called")
		author, _ := cmd.Flags().GetString("author")
		fmt.Println("作者是:", author)

		var x int
		//string 转换为 int
		for _, v := range args {
			tmp, _ := strconv.Atoi(v)
			x += tmp
		}
		fmt.Println("x is ", x)
	},
}

func init() {
	rootCmd.AddCommand(versionCmd)

	testCmd.AddCommand(versionCmd)

	// 添加参数
	versionCmd.Flags().StringP("author", "n", "default", "name") //名称,简写,默认值,描述

}

🚀 编译结果如下:

PS D:\文档\最近的\awesome-golang\docs\go-advancend\code\cobra\clid> .\clid.exe version -n 老王 123 12 412 543 12
version called
作者是: 老王
x is  1102

END 链接