このエントリーをはてなブックマークに追加

はじめに

GolangでCLIツールを作りたくて、ググった結果、cobraを使うことに決めました。
使ってみた結果、非常によかったです。
本格的なコマンドを非常に簡単に実装することができました。
cobraの使い方についてはすでに色々な情報がありますが、自分のためにもまとめておきます。

なんでcobra

cobraはメジャーなCLIツールで採用されていたのが一番の理由です。
このブログを作ってるhugoもcobraを使っていました。
hugoのコードも参考にさせていただきました。

cobraの始め方

cobraを始めるにあたり、以下の記事を参考にさせていただきました。

今回は簡単なサンプルとして、helloコマンドを実装してみます。

cobraのインストール

まずはインストールします。…とはいえ、go getするだけです。

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

セットアップ

cobraには addinit の2つのコマンドがあります。

  • init ・・・ cobraプロジェクトの初期化
  • add ・・・ 新しいコマンドの追加

cobraの初期化

まずは初期化をします。initするだけです。

1
2
3
4
5
6
$ cobra init hello
Your Cobra application is ready at
/path/to/go/src/hello

Give it a try by going there and running `go run main.go`.
Add commands to it by running `cobra add [cmdname]`.

initすると GOPATH にコマンドのプロジェクトが初期化されます。
プロジェクトは↓の構成です。基本的にはcmdの中にコマンドを実装していきます。

1
2
3
4
5
6
$ tree
.
├── LICENSE
├── cmd
│   └── root.go
└── main.go

helloコマンドの実装

まずは hello と打つと world と表示するコマンドを作ります。
cmd/root.go を編集します。参考サイトを参考にして、最初の状態からは少しリファクタしています。

rootCmdの実装

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
func newRootCmd() *cobra.Command {
	return &cobra.Command{
		Use:   "hello",
		Short: "This is hello command",
		Long:  `This is hello comand long long description`,
		RunE: func(cmd *cobra.Command, args []string) error {
			fmt.Println("world")
			return nil
		},
	}
}

rootCmdの初期化

1
var rootCmd = newRootCmd()

コマンドのエントリーポイントとなる Execute は特に変更していません。
この状態で実行してみます。

1
2
$ go run main.go
world

無事にworldと表示されました。

サブコマンドの実装

次にサブコマンドを実装してみます。
hello world ken とコマンドを打つと ハローkenさん と答えるようにしてみます。
まずはサブコマンドを追加します。

1
$ cobra add world

すると、cmdの中に world.go が出来ます。

自動生成されたコードにまずはバリデーションを追加してみます。
引数の名前は必須にしたいので、引数が1より小さい場合はエラーにします。
引数のチェックは Args を使うと行えます。

1
2
3
4
5
6
	Args: func(cmd *cobra.Command, args []string) error {
		if len(args) < 1 {
			return errors.New("requires name")
		}
		return nil
	},

実行してみます。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
$ go run main.go world ken
world called
$ go run main.go world
Error: requires name
Usage:
  hello world [flags]

Flags:
  -h, --help   help for world

Global Flags:
      --config string   config file (default is $HOME/.hello.yaml)

requires name
exit status 1

正しく実行すると、デフォルトのメッセージが表示されます。
バリデーションに引っかかるとエラーメッセージが表示されて、そのままhelpが出てきます。
今回、特にhelp関連は何も変更していないのですが、デフォルトでこのhelpメッセージを作ってくれます。

次にコマンドを実装します。
デフォルトでは Run というFieldに実装するようになっているのですが、エラーが出ても返すことが出来ないので RunE を実装するほうがよさそうです。

1
2
3
4
	RunE: func(cmd *cobra.Command, args []string) error {
		fmt.Printf("ハロー%sさん", args[0])
		return nil
	},

実行すると、想定どおりに実行されています。

1
2
$ go run main.go world ken
ハローkenさん

これでサブコマンドも実装することが出来ました。

まとめ

このようにcobraを使えばこれまで使っていたようなコマンドラインツールが簡単に出来てしまいます。
CLI使ったことない人も是非、試してみて下さい。
今回作ったサンプルはこちらのリポジトリに入れてます。

https://github.com/ken-aio/cobra-sample