Go命令行工具cobra

cobra是go下的一个命令行解析库。写livermore的时候,需要用到命令行解析,就找到了它。进入项目主页看了一下,发现蛮多高大上的项目也在使用,比如docker,还有本博客程序hugo,和hugo是同一个作者。

好吧,开始了解一下cobra是如何使用的。项目主页上文档已经很完备,使用非常简单。这里再简单介绍一下。

基本概念

这里使用livermore做例子来介绍。例如
livermore -v fetch sh600036 -s codes.txt

livermore 应用程序的名称
fetch 具体的command,这里是获取股票基本信息
sh600036 fetch的参数 arg, 股票代码
-v flag,是否开启verbose模式,打印debug信息
-s fetch的一个flag,具体值: “codes.txt””

实现

文件结构如下

  ▾ livermore/
    ▾ cmd/
        version.go
        fetch.go
        root.go
      main.go

整个程序的入口,main

整个程序入口main.go, 具体的命令都定义在cmd中,每个命令一个文件,这样比较清晰。 在main.go中,只需要加载cobra命令的配置等信息就可以了。

package main

import "github.com/wuyq101/livermore/cmd"

func main() {
	if err := cmd.RootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(-1)
	}
}

定义根命令 livermore

刚刚在main中加载的root cmd, 在cmd/root.go中定义livermore这个命令.

package cmd

import (
	"fmt"
	"github.com/spf13/cobra"
)

var Verbose bool

var RootCmd = &cobra.Command{
	Use:   "livermore",
	Short: "Livermore is a command line tool for stock data fetch and display",
	Long: `Livermore is a command line tool for stock data fetch and display.
		   It was written in Go. 
	       More detail please visit : https://github.com/wuyq101/livermore
		`,
	Run: func(cmd *cobra.Command, args []string) {
		// Do Stuff Here
		fmt.Println("This is test from cobra")
	},
}

func init() {
	RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
}

定义子命令 version

在cmd/version.go中定义version命令, 并且将它加入到livermore中。

package cmd

import (
	"fmt"
	"github.com/spf13/cobra"
)

func init() {
	RootCmd.AddCommand(versionCmd)
}

var versionCmd = &cobra.Command{
	Use:   "version",
	Short: "Print version numbre of Livermore",
	Long:  "All software has versions. This is Livermore's",
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("Livermore v0.1 --head")
	},
}

定义子命令fetch

在cmd/fetch.go中定义fetch命令,并且将它加入到livermore中。

package cmd

import (
	"fmt"
	"github.com/spf13/cobra"
)

func init() {
	fetchCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
	RootCmd.AddCommand(fetchCmd)
}

var Source string

var fetchCmd = &cobra.Command{
	Use:   "fetch",
	Short: "Fetch stock data by code",
	Long: `Fetch stock data by code
	
	`,
	Run: func(cmd *cobra.Command, args []string) {
		fmt.Println("Start to fetch stock data ...")
		fmt.Printf("args %q \n", args)
		fmt.Println("Version ", Verbose)
		fmt.Println("Source", Source)
	},
}

Flag

Flag是另一种类型的参数,可以方便的控制command的具体行为。

全局范围的flag

如果是全局范围内的flag,如上例-v -verbose, 这个是全局性的,我们就加入到root cmd中。

RootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")

子命令的flag

如果是某个子命令特有的flag, 如上例中-s -source, 这个只在fetch命令中有效。

fetchCmd.Flags().StringVarP(&Source, "source", "s", "", "Source directory to read from")

其他

集成cobra之后,cobra自动支持 –help等参数。help的输出默认就提供了,你也可以在自己重新定义。