Home  >  Article  >  Backend Development  >  A common golang library cobra

A common golang library cobra

藏色散人
藏色散人forward
2021-05-13 11:53:282586browse

The following tutorial column from golang will introduce you to cobra, a common golang library. I hope it will be helpful to friends in need!

cobra is a library in the go language that can be used to write command line tools. Usually we can see git pull , docker container start , apt install and other commands, which can be easily implemented with corba. In addition, go language It is easy to compile into a binary file. This article will implement a simple command line tool.

Write a specific example, design a command called blog, with four sub-commands

 blog new [post-name] :创建一篇新的blog
 blog list   :列出当前有哪些文章
 blog delete [post-name]: 删除某一篇文章
 blog edit [post-name]:编辑某一篇文章

The plan has the following steps

  • create Module
  • Use cobra’s command line to create a command line entry
  • Use cobra’s command line to create subcommands
  • Write functional logic

Create a module

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

Create a command line entry

Speaking of the command line, you may think of bash’s getopt or java’s jcommand, which can parse various styles of command lines, but usually these command lines There is a fixed way of writing. Generally, if you can’t remember this way of writing, you need to find a template and refer to the following. In addition to parsing the command line, cobra also provides a command line that can generate templates. Install this command line first, and add the library dependencies to go.mod

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

cobra will be installed in the $GOPATH\bin directory. Pay attention to adding it to the PATH in the environment variable.

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

The directory structure is as follows:

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

Compile it

go build  -o blog .

Execute it

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

The command line will be created. It seems that you don’t need to write a single line of code. , because as the understanding deepens, the generated code needs to be adjusted later, so it is still necessary to understand the routine of cobra code.

Cobra code routine

There are three concepts, command, flag and args, for example:

go get -u test.com/a/b

Here get is commond (this is more special), -u is flag, test.com/a/b is args

Then the command line is composed of three parts, so it is necessary to define some basic information of the

  • command itself, represented by command, and the specific object They are some features or options of the cobra.Command
  • command, represented by flag. The specific object is the last parameter of flag.FlagSet
  • , represented by args, usually []string

Another concept is subcommands. For example, get is the subcommand of go. This is a tree-structured relationship.

I can use the go command, or I can use the go get command

For example: root.go defines the root command, and also defines the flag in init. If it is specifically executed, Just fill in the Run field.

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

}

If you need subcommands, you need to give rootCmd.AddCommand() other commands in init. Other subcommands are usually written in a separate file and have a global variable so that rootCmd can add it

Create subcommand

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

New.go, delete.go,list.go,edit.go

Add function code

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 This is a little troublesome, because if you call a program such as vim to open the file , and the golang program itself needs to detach to exit. Let’s put it aside for now (TODO)

Compile and test

I am testing on window, Linux is simpler

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>

Summary

cobra is an efficient command line The parsing library uses cobra's scaffolding to quickly implement a command line tool. If you need more detailed control, you can refer to cobra's official documentation.

The above is the detailed content of A common golang library cobra. For more information, please follow other related articles on the PHP Chinese website!

Statement:
This article is reproduced at:cnblogs.com. If there is any infringement, please contact admin@php.cn delete