溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

如何在golang中使用cobra庫(kù)

發(fā)布時(shí)間:2021-05-13 16:17:17 來(lái)源:億速云 閱讀:188 作者:Leah 欄目:編程語(yǔ)言

如何在golang中使用cobra庫(kù)?很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來(lái)學(xué)習(xí)下,希望你能有所收獲。

cobra  是 go 語(yǔ)言的一個(gè)庫(kù),可以用于編寫(xiě)命令行工具。通常我們可以看到git pull  、docker container start  、apt install 等等這樣命令,都可以很容易用corba來(lái)實(shí)現(xiàn),另外,go 語(yǔ)言是很容易編譯成一個(gè)二進(jìn)制文件,本文將實(shí)現(xiàn)一個(gè)簡(jiǎn)單的命令行工具。

具體寫(xiě)一個(gè)例子, 設(shè)計(jì)一個(gè)命令叫blog, 有四個(gè)子命令

 blog new [post-name] :創(chuàng)建一篇新的blog
 blog list   :列出當(dāng)前有哪些文章
 blog delete [post-name]: 刪除某一篇文章
 blog edit [post-name]:編輯某一篇文章

計(jì)劃有以下幾個(gè)步驟

  • 創(chuàng)建模塊

  • 用cobra的命令行,創(chuàng)建命令行入口

  • 用cobra的命令行,創(chuàng)建子命令

  • 編寫(xiě)功能邏輯

創(chuàng)建模塊

$ go mod init github.com/shalk/blog
go: creating new go.mod: module github.com/shalk/blog

創(chuàng)建命令行入口

說(shuō)到命令行,可能會(huì)想到bash的getopt 或者 java 的jcommand,可以解析各種風(fēng)格的命令行,但是通常這些命令行都有固定的寫(xiě)法,這個(gè)寫(xiě)法一般還記不住要找一個(gè)模板參考以下。cobra除了可以解析命令行之外,還提供了命令行,可以生成模板。先安裝這個(gè)命令行, 并且把庫(kù)的依賴加到go.mod里

$ go get -u github.com/spf13/cobra/cobra

cobra會(huì)安裝到$GOPATH\bin 目錄下,注意環(huán)境變量中把它加入PATH中

$ cobra init --pkg-name github.com/shalk/blog -a shalk -l mit
Your Cobra applicaton is ready at
D:\code\github.com\shalk\blog

目錄結(jié)構(gòu)如下:

./cmd
./cmd/root.go
./go.mod
./go.sum
./LICENSE
./main.go

編譯一下

go build  -o blog .

執(zhí)行一下

$blog -h
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.

命令行就創(chuàng)建好了,看上去一行代碼也不用寫(xiě),由于隨著了解的深入,后面需要調(diào)整生成的代碼,還是要了解一下cobra代碼的套路。

cobra代碼的套路

有三個(gè)概念,command、flag和args  ,例如:

go get -u test.com/a/b

這里 get 就是commond(這里比較特殊), -u 就是flag, test.com/a/b 就是args

那么命令行就是有三部分構(gòu)成,所以需要定義好這個(gè)

  • 命令自身的一些基本信息,用command表示,具體對(duì)象是 cobra.Command

  • 命令的一些標(biāo)致或者選項(xiàng),用flag表示,具體對(duì)象是 flag.FlagSet

  • 最后的參數(shù),用args表示,通常是[]string

還有一個(gè)概念是子命令,比如get就是go的子命令,這是一個(gè)樹(shù)狀結(jié)構(gòu)的關(guān)系。

我可以使用go命令,也可以使用 go get命令

例如:  root.go,定義了root命令,另外在init里面 定義了flag,如果它本身有具體執(zhí)行,就填充Run字段。

// rootCmd represents the base command when called without any subcommands
var rootCmd = &cobra.Command{
	Use:   "blog",
	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() {
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}

func init() {
	cobra.OnInitialize(initConfig)

	// 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/.blog.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")

}

如果需要子命令,就需要在init 里,給 rootCmd.AddCommand() 其他的command,其他的子命令通常也會(huì)單獨(dú)用一個(gè)文件編寫(xiě),并且有一個(gè)全局變量,讓rootCmd可以add它

創(chuàng)建子命令

D:\code\github.com\shalk\blog>cobra add  new
new created at D:\code\github.com\shalk\blog

D:\code\github.com\shalk\blog>cobra add  delete
delete created at D:\code\github.com\shalk\blog

D:\code\github.com\shalk\blog>cobra add  list
list created at D:\code\github.com\shalk\blog

D:\code\github.com\shalk\blog>cobra add  edit
edit created at D:\code\github.com\shalk\blog

cmd 目錄下增加了 new.go, delete.go,list.go,edit.go

增加功能代碼

new.go

var newCmd = &cobra.Command{
	Use:   "new",
	Short: "create new post",
	Long:  `create new post `,
	Args: func(cmd *cobra.Command, args []string) error {
		if len(args) != 1 {
			return errors.New("requires a color argument")
		}
		return nil
	},
	Run: func(cmd *cobra.Command, args []string) {
		fileName := "posts/" + args[0]
		err := os.Mkdir("posts", 644)
		if err != nil {
			log.Fatal(err)
		}
		_, err = os.Stat( fileName)
		if os.IsNotExist(err) {
			file, err := os.Create(fileName)
			if err != nil {
				log.Fatal(err)
			}
			log.Printf("create file %s", fileName)
			defer file.Close()
		} else {
		}
	},
}

list.go

var listCmd = &cobra.Command{
	Use:   "list",
	Short: "list all blog in posts",
	Long: `list all blog in posts `,
	Run: func(cmd *cobra.Command, args []string) {
		_, err := os.Stat("posts")
		if os.IsNotExist(err) {
			log.Fatal("posts dir is not exits")
		}
		dirs, err := ioutil.ReadDir("posts")
		if err != nil {
			log.Fatal("read posts dir fail")
		}
		fmt.Println("------------------")
		for _, dir := range dirs {
			fmt.Printf(" %s\n", dir.Name() )
		}
		fmt.Println("------------------")
		fmt.Printf("total: %d blog\n", len(dirs))

	},
}

delete.go

var deleteCmd = &cobra.Command{
	Use:   "delete",
	Short: "delete a post",
	Long: `delete a post`,
	Args: func(cmd *cobra.Command, args []string) error {
		if len(args) != 1 {
			return errors.New("requires a color argument")
		}
		if strings.Contains(args[0],"/") || strings.Contains(args[0],"..") {
			return errors.New("posts name should not contain / or .. ")
		}
		return nil
	},
	Run: func(cmd *cobra.Command, args []string) {
		fileName := "./posts/" +  args[0]
		stat, err := os.Stat(fileName)
		if os.IsNotExist(err) {
			log.Fatalf("post %s is not exist", fileName)
		}
		if stat.IsDir() {
			log.Fatalf("%s is dir ,can not be deleted", fileName)
		}
		err = os.Remove(fileName)
		if err != nil {
			log.Fatalf("delete %s fail, err %v", fileName, err)
		} else {
			log.Printf("delete post %s success", fileName)
		}
	},
}

edit.go 這個(gè)有一點(diǎn)麻煩,因?yàn)槿绻{(diào)用一個(gè)程序比如vim 打開(kāi)文件,并且golang程序本身要退出,需要detach。暫時(shí)放一下(TODO)

編譯測(cè)試

我是window測(cè)試,linux 更簡(jiǎn)單一點(diǎn)

PS D:\code\github.com\shalk\blog> go build -o blog.exe .
PS D:\code\github.com\shalk\blog> .\blog.exe list
------------------
------------------
total: 0 blog
PS D:\code\github.com\shalk\blog> .\blog.exe new blog1.md
2020/07/26 22:37:15 create file posts/blog1.md
PS D:\code\github.com\shalk\blog> .\blog.exe new blog2.md
2020/07/26 22:37:18 create file posts/blog2.md
PS D:\code\github.com\shalk\blog> .\blog.exe new blog3.md
2020/07/26 22:37:20 create file posts/blog3.md
PS D:\code\github.com\shalk\blog> .\blog list
------------------
 blog1.md
 blog2.md
 blog3.md
------------------
total: 3 blog
PS D:\code\github.com\shalk\blog> .\blog delete blog1.md
2020/07/26 22:37:37 delete post ./posts/blog1.md success
PS D:\code\github.com\shalk\blog> .\blog list
------------------
 blog2.md
 blog3.md
------------------
total: 2 blog
PS D:\code\github.com\shalk\blog> ls .\posts\


    目錄: D:\code\github.com\shalk\blog\posts


Mode                LastWriteTime         Length Name
----                -------------         ------ ----
-a----        2020/7/26     22:37              0 blog2.md
-a----        2020/7/26     22:37              0 blog3.md


PS D:\code\github.com\shalk\blog>

golang適合做什么

golang可以做服務(wù)器端開(kāi)發(fā),但golang很適合做日志處理、數(shù)據(jù)打包、虛擬機(jī)處理、數(shù)據(jù)庫(kù)代理等工作。在網(wǎng)絡(luò)編程方面,它還廣泛應(yīng)用于web應(yīng)用、API應(yīng)用等領(lǐng)域。

看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注億速云行業(yè)資訊頻道,感謝您對(duì)億速云的支持。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI