0%

Cobra一个很棒的命令行库

Cobra is a library for creating powerful modern CLI applications.

安装

获取最新版cobra

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

导入至项目中

import "github.com/spf13/cobra"

为了更快的创建一个基于cobra的命令行应用,cobra提供了一个命令行工具cobra-cli,就像vuevue-cli

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

cobra-cli用法

使用cobra-cli初始化项目

如果你已经有项目了跳过这一步

~ cd go/src/myapp
~ cobra-cli init
# 你的项目应该像下面这样
.
├── LICENSE
├── cmd
│   └── root.go
├── go.mod
├── go.sum
└── main.go

可选flags

可以使用--author向其提供作者。例如cobra-cli init --author "Jianglei jianglei.new@gmail.com"

使用--license创建开源协议 cobra-cli init --license apache

使用--viper自动设置viperviper是一个处理配置文件和环境变量的工具,可以和Cobra无缝衔接。

向已初始化的项目添加子命令

cobra-cli add serve
cobra-cli add config
cobra-cli create -p 'configCmd'

-p 选项将config设置成了create的父命令,用法:./app config create

cobra-cli add支持所有相同的可选flags cobra-cli init(如上所述)。

注意:命令名称使用驼峰命名法。否则,您将遇到错误。例如,cobra-cli add add-user不正确,但cobra-cli add addUser有效。

运行这三个命令后,目录结构如下:

.
├── LICENSE
├── cmd
│ ├── config.go
│ ├── create.go
│ ├── root.go
│ └── serve.go
├── go.mod
├── go.sum
└── main.go

现在我们已经掌握了cobra-cli的基本使用,能够初始化cobra命令行应用了。

使用配置文件自动生成配置

你可以在家目录创建一个~/.cobra.yaml文件,这样就不用每次创建命令的时候加上flags

示例配置文件:

author: Jianglei <jianglei.new@gmail.com>
license: apache
useViper: false

你可以设置不同的license,例如: GPLv2GPLv3LGPLAGPLMIT2-Clause BSD3-Clause BSD

还可以通过设置为不指定许可证license:none也可以指定自定义许可证:

author: Jianglei <jianglei.new@gmail.com>
year: 2020
license:
header: This file is part of CLI application foo.
text: |
{{ .copyright }}

This is my license. There are many like it, but this one is mine.
My license is my best friend. It is my life. I must master it as I must
master my life.

Cobra Demo

go-learning/main.go

/*
Copyright © 2023 NAME HERE <EMAIL ADDRESS>

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 "github.com/jianglei-w/go-learning/cmd"

func main() {
cmd.Execute()
}

go-learning/cmd/root.go

package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

func init() {
rootCmd.PersistentFlags().BoolVarP(&Verbose, "verbose", "v", false, "verbose output")
rootCmd.PersistentFlags().StringVarP(&Source, "source", "s", "", "Source directory to read from")
rootCmd.Flags().StringVarP(&Region, "region", "r", "", "AWS region (required)")
rootCmd.MarkFlagRequired("region")
}

var (
Region string
Verbose bool
Source string
)

var rootCmd = &cobra.Command{
Use: "go-learning",
Long: "learning-go is a Test CLI",
Short: "It's Test",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Run go-learning...")

fmt.Printf("Verbose: %v\n", Verbose)
fmt.Printf("Source: %v\n", Source)
fmt.Printf("Region: %v\n", Region)
},
TraverseChildren: true,
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

go-learning/cmd/verison.go

package cmd

import (
"errors"
"fmt"

"github.com/spf13/cobra"
)

var versionCmd = &cobra.Command{
Use: "version",
Short: "Show version",
Long: "Print the app version",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("go-learning version v1.0")
},
Args: func(cmd *cobra.Command, args []string) error {
if len(args) < 1 {
return errors.New("requires at least one arg")
}
if len(args) > 4 {
return errors.New("the number of args cannot exced 4")
}
if args[0] != "a" {
return errors.New("frist argument must be 'a'")
}
return nil
},
}

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

go-learning/cmd/print.go

package cmd

import (
"fmt"

"github.com/spf13/cobra"
)

var (
printFlag string
printCmd = &cobra.Command{
Use: "print [OPTIONS] [COMMANDS]",
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("run print...")
fmt.Printf("printFlags: %v\n", printFlag)
fmt.Printf("Source: %v\n", Source)
},
}
)

func init() {
rootCmd.AddCommand(printCmd)

printCmd.Flags().StringVarP(&printFlag, "flag", "f", "", "print flag for local")
}