Featured image of post cobraでかんたんなCLIツールをつくった

cobraでかんたんなCLIツールをつくった

Goでコマンドラインツール

golangでCLIツールを作るときに引数とかサブコマンドをいい感じにしてくれるライブラリのcobraを試した.


やったことのまとめ

cobraを使ってコマンドラインであいさつするおもちゃgreetingをつくった.

# hello
$ greeting hello hoge fuga piyo --message 'Nice to meet you!'
Hello, hoge, fuga, and piyo!
Nice to meet you!

# こんにちは
$ greeting hello 鈴木 --message 'お会いできて嬉しいです!' -l ja
鈴木さん, こんにちは!
お会いできて嬉しいです!

# goodbye
$ greeting goodbye hoge fuga piyo
Goodbye, hoge, fuga, and piyo!

# さようなら
$ greeting goodbye A -l ja
Aさん, さようなら!

つかうもの

  • macOS Mojave 10.14
  • go version go1.14.6 darwin/amd64
  • cobra v1.0.0

やったこと

cobraのインストールとサンプルコードの作成

cobraはこれ自身がコマンドとしても提供されているので, まずはこれをインストールする.

# cobraをインストール
$ go get -u github.com/spf13/cobra/cobra
$ which cobra
/GOPATH/bin/cobra
$ cobra
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:
  cobra [command]

Available Commands:
  add         Add a command to a Cobra Application
  help        Help about any command
  init        Initialize a Cobra Application

Flags:
  -a, --author string    author name for copyright attribution (default "YOUR NAME")
      --config string    config file (default is $HOME/.cobra.yaml)
  -h, --help             help for cobra
  -l, --license string   name of license for the project
      --viper            use Viper for configuration (default true)

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

cobra initを使うと動く状態のサンプルコードを生成してくれる.1
昔は空のディレクトリじゃないとできなかったみたいだけど, 今は気にしなくて大丈夫.

# 新規ディレクトリを作成+go.modを作成
$ mkdir -p greeting && cd greeting
$ go mod init github.com/uzimihsr/greeting
go: creating new go.mod: module github.com/uzimihsr/greeting

# サンプルコードの作成
$ cobra init --pkg-name github.com/uzimihsr/greeting
Your Cobra application is ready at
/path/to/greeting
$ tree .
.
├── LICENSE
├── cmd
│   └── root.go
├── go.mod
└── main.go

1 directory, 4 files

作成されたサンプルコードはこんな感じ.

試しに動かしてみる.

# アプリの実行
$ go run main.go
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.
# root.goで設定されたヘルプメッセージ

ちゃんと動いた.

さらに, cobra addでサブコマンドを作成できる.
追加したサブコマンドのファイルはroot.goと同じくcmd配下に作成される.

# サブコマンド(hello)の作成/実行
$ cobra add hello
hello created at /Users/uzimihsr/Workspace/greeting
$ ls cmd
hello.go root.go

$ go run main.go hello
hello called
$ go run main.go hello -h
A longer description that spans multiple lines and likely contains examples
and usage of using your command. 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:
  greeting hello [flags]

Flags:
  -h, --help   help for hello

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

サブコマンドの実装

あとはこのルートコマンド(root.go)とサブコマンド(hello.go)をいじっていく.
どちらもinit()関数で引数やコマンドに必要な変数の設定を行い,
Command.Runのfunc()で実際に行う処理を記述しているので, この形式に従っていろいろいじってみる.

最終的なディレクトリ構造はこんな感じ.
出会いと別れの挨拶をするサブコマンドcmd/hello.gocmd/goodbye.goを実装した.

$ tree .
.
├── cmd
│   ├── goodbye.go
│   ├── hello.go
│   └── root.go
├── go.mod
├── go.sum
└── main.go

1 directory, 6 files

実際に動かしてみる.
go installするとPATHが通ってすぐ使えるようになるのでべんり.

# ビルドして実行
$ go build
$ ./greeting hello World
Hello, World!

# GOPATHが通っている場合はinstallするとパスが通る
$ go install
$ which greeting
$GOPATH/bin/greeting

# -l で言語(en/ja)の指定ができる
$ greeting goodbye A B -l ja
Aさん, Bさん, さようなら!

# --message で追加のメッセージを指定できる
$ greeting hello A B C --message 'Nice to meet you!'
Hello, A, B, and C!
Nice to meet you!

# goodbyeには敢えて --message のflagをつけていないので指定するとエラーになる
$ greeting goodbye A --message 'See you again!'
Error: unknown flag: --message
Usage:
  greeting goodbye [NAME] [flags]

Flags:
  -h, --help   help for goodbye

Global Flags:
  -l, --lang string   Language : en, ja (default "en")

unknown flag: --message

# 引数の数が不正でもエラーになる
$ greeting hello
Error: requires at least 1 arg(s), only received 0
Usage:
  greeting hello [NAME] [flags]

Flags:
  -h, --help             help for hello
  -m, --message string   Help message for toggle

Global Flags:
  -l, --lang string   Language : en, ja (default "en")

requires at least 1 arg(s), only received 0

やったぜ.
機能はしょぼいけど, サブコマンドごとに違う機能を持つCLIツールができた.

おわり

Cobraを使って簡単なCLIツールを作った.
サブコマンドごとにflag(オプション)が管理できたり, Argsで引数の条件を指定できたりするのがいいと思う.
今までGoでCLIを作るときは標準パッケージのflagを使ってたけど,
これからはCobraでサクッと作るようにしたい.

おまけ

ねこのかわいい肉球