Blog
ブログ

2021年09月08日

CobraでCLIツール、つくってみませんか?


こんにちは。
最近、業務でGo(プログラミング言語)を用いたCLIツールを開発する機会がありました。
私はこれまでGoやCLIツールの開発経験はあまりありませんでしたが、今回紹介するCobraを用いると簡単にCLIツールの作成ができました。


CobraはGo向けのCLIフレームワークです。
サブコマンドの作成やPOSIX準拠のフラグの実装、Usageの自動生成等の機能を提供してくれます。

今回はCobraを使った簡単なCLIツールの作成方法について紹介したいと思います。


Go&Cobraの導入

まずはGoのインストールです。
これは非常にシンプルで、公式ドキュメントに従いダウンロードしたインストーラーを実行/展開するだけ。
Linux, Mac, Windowsに対応しています。


つぎに、Cobraのインストールです。
これも公式に従い、下記のコマンドでインストールできます。

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

開発環境が整ったら、早速CLIツールを作成してみましょう。

Cobraによるコマンド追加

今回は、ねこのアスキーアートを表示するサブコマンドcatと、いぬのアスキーアートを表示するサブコマンドdogをもつCLIツールを作ります。

まず、moduleを作成します。

$ go mod init cli/aa

ここでcli/aaはimportpathを表しており、一般にアクセス可能なリポジトリのURIを入力しますが、今回は公開予定はないためcli/aaとしています。

つぎに、cobra initでCLIツールのテンプレートを作成します。

$ cobra init --pkg-name cli/aa --viper=false

この状態で実行してみると



上記のような出力になります。


ここにコマンドを追加していきます。
コマンドの追加は下記のように行います。

$ cobra add cat

すると、root/cmd/の下にcat.goが追加されています。
この状態を実行してみると

 


自動でUsageが追加されています!


追加したcatコマンドは



cat calledを出力するコマンドとして生成されています。

早速、ねこのアスキーアートを表示するように書き換えてみましょう。

アスキーアートCLIツールの作成

今回は、ねこのアスキーアートとしてこちらを使います。



cat_aa.txtとしてrootディレクトリに置き、catコマンドの実行でこのテキストファイルを読み取り、標準出力に出力します。

func printAAFromTxt(fp string) {
  b, err := os.ReadFile(fp)
  if err != nil {
    fmt.Println(err)
  }
  fmt.Print(string(b))
}

テキストファイル読み取り/標準出力関数はこんな感じでしょうか。
ファイルパスを受け取り、中身を一括で読み込み標準出力に出力しています。


これをcatCmd構造体のRUNフィールドに追加します。(cat calledを出力しているところ)
ファイルパスは先ほどのcat_aa.txtへのパスを指定します。

実行してみると



しっかり表示されました!


同様にdogコマンドも追加してみましょう

$ cobra add dog

dog.goが生成されているはずです。

テキストファイル読み取り/標準出力関数は、先ほどとおなじものを使えばよさそうです。
dog, cat共通で利用するのでcat.goから切り出してみましょう。


今回は、rootディレクトリに新たにutilsディレクトリを追加し、utilsパッケージとして切り出します。
ここで注意する点は、Goでは、名前の先頭一文字が大文字か小文字かによって外部パッケージから参照可能か決定される点です。
いま、テキストファイル読み取り/標準出力関数は、cat.go, dog.goとは異なるutilsパッケージに属しています。
このため、関数名の先頭一文字を外部から参照可能な大文字にする必要があるということです。

切り出したテキストファイル読み取り/標準出力関数はこんな感じです。

package utils

import (
  "fmt"
  "os"
)

func PrintAAFromTxt(fp string) {
  b, err := os.ReadFile(fp)
  if err != nil {
    fmt.PrintLn(err)
  }
}

さて、dog.goからutilsパッケージのテキストファイル読み取り/標準出力関数を呼び出せるようutilsパッケージをimportしましょう。
Goにおけるインポートでは絶対パスを指定してimportする方法が一般的なようです。
今回、module作成時にimportpathをcli/aaとしたので、utilsパッケージのimportはcli/aa/utilsとなります。

あとはimportしたテキストファイル読み取り/標準出力関数をdogCmdのRUNフィールドに追加するだけです。

実行すると



かわいいですね。

クロスコンパイル

Goではビルド時に環境変数GOOS/GOARCHに実行環境のOS/アーキテクチャを指定することで簡単にクロスコンパイルが可能です。

windows/amd64およびlinux/amd64向けにコンパイルする場合は以下のようにできます。

GOOS=windows GOARCH=amd64 go build -o aa_windows.exe main.go
GOOS=linux GOARCH=amd64 go build -o aa_linux main.go

作成された実行ファイルでも動作を確認してみましょう。

linuxでは



実行できていますね。


windowsでは


 


改行文字が¥ですね。

おわりに

今回、フラグの追加やviperによる設定の読み込み等の優れた機能について割愛しましたが、興味を持たれた方はぜひ調べてみてください。
そして、実際に開発を行ってみてください。
普段よく使うコマンドのCobra実装や、あったら便利なコマンドの開発は面白い学習課題になるかと思います。


とりとめのない文章となってしまいましたが、ここまでお読みいただきありがとうございました。

このページの先頭へ