けーたうぇぶ

ITエンジニアの技術ネタや日々の生活のことを書き連ねます。

Go初心者がcobraのボイラープレートを作成・理解する

こんにちは、最近になってやっと休みの日にも多少の余裕がでてきました。
とりあえずGoとcobraをインストールしてみたので、cobra-cliで出来上がったボイラープレートを理解していきます。

cobraのボイラープレートを作成する

# プロジェクトフォルダtestに移動
$ cd test

# Go Modules を初期化する
$ go mod init test-cli
go: creating new go.mod: module test-cli

$ ls
main.go

# cobra-cliアプリケーションを初期化する
$ cobra-cli init
Your Cobra application is ready at
/Users/xxxxxxx/Projects/test

$ ls
LICENSE  cmd    go.mod  go.sum  main.go

# help コマンドをプロジェクトに追加する
$ cobra-cli add help
help created at /Users/xxxxxxx/Projects/test

cobra-cliの公式ドキュメント に記載の通りにコマンドを実行し、まずはボイラープレートが完成しました。
テスト用に作成したので go mod init test-cli としていますが、公開予定がある場合は test-cli のところをGitHubのパスにしておくようです。

開発を進めながら、パッケージを入れていくと go.modgo.sum が自動で書き換えられるようですが、自らこれらのファイルを触る必要はないようです。

ここまでのステップでフォルダは下記のようになっています。

$ tree .
.
├── LICENSE
├── cmd
│   ├── help.go
│   └── root.go
├── go.mod
├── go.sum
└── main.go

root.go を理解する

$ cd cmd

$ go run test-cli
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.

Usage:
  test-cli [command]

Available Commands:
  completion  Generate the autocompletion script for the specified shell
  help        A brief description of your command
  help        Help about any command

Flags:
  -h, --help     help for test-cli
  -t, --toggle   Help message for toggle

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

go run test-cli と実行するとすでにコマンドを実行できるようになっており、内部的には root.go が呼び出されているようです。
ここでは root.go が何をしているのか、ざっくり理解していこうと思います。
コードブロックに日本語でコメント入れています。

Cobra documentation

こちらの公式ドキュメントを眺めてみるとより詳しいことが分かってきそうです。

/*
Copyright © 2022 NAME HERE <EMAIL ADDRESS>

*/

// cmdパッケージにコードを入れることを示している
package cmd

// 使用するパッケージをインポートする
import (
    "os"
    "github.com/spf13/cobra"
)

// rootCmd変数に記述された内容は go run main.go で実行される
// 例えばconfigやversionといったコマンドを追加したときはrootCmdにそれらのコマンドが追加されることになる(=rootCmdにコマンドの実行内容等が全部入っているイメージ)
var rootCmd = &cobra.Command{
        // CLIアプリケーションの名称がそのまま入る。コマンドを追加したときはここにコマンド名が入ることになる。
    Use:   "test-cli",

        // 簡単なCLIアプリケーション or コマンド の説明を書く
    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.`,

        // このように記載すると、最低1つはコマンドにパラメータを渡さないといけなくなるようです
        // 「https://umarcor.github.io/cobra/」の「Positional and Custom Arguments」に他に使用できるものを確認できます
    Args: cobra.MinimumNArgs(1),

    // コマンド実行時に何か実行したい時に使用する(rootCmdではあえてここを使用する必要はなさそう)
    Run: func(cmd *cobra.Command, args []string) {
            // 「go run main.go hoge」で実行すると「[hoge]」がプリントされる
            fmt.Println(args)
        },
}

// 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() {

        // 上で用意したrootCmdがここで実行される
    err := rootCmd.Execute()

        // エラーが発生していれば終了する
    if err != nil {
        os.Exit(1)
    }
}

func init() {
    // フラグやconfigの設定が可能
    // 常に同じとなるフラグをここで指定しておけば、CLIアプリケーション全体でグローバルになる

        // 常に同じになるフラグ(Persistent Flags)はこのように指定する
    rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.test-cli.yaml)")

        // ユーザーが指定できるフラグ(Local Flags)はこのように設定する
        // ユーザーが直接指定しないと実行されない
    rootCmd.Flags().BoolP("toggle", "t", false, "Help message for toggle")
}

公式ドキュメントと睨みっこしながら、一通り root.go のやっていることが理解できました。
とりあえずは必要なコマンドを追加しながら進めてみようと思います。