GoのcobraでCLIを作った

f:id:excite-kazuki:20220114192237p:plain

はじめに

エキサイト株式会社 バックエンドエンジニアの山縣です。

既存サービスのリビルドを進めていく上で、Redisのキャッシュ操作を行うためのツールが欲しいという要望がでました。 そこで、Goのcobraを使ってキャッシュ操作を行うCLIを作成しました。 本記事ではcobraの使い方と実際に作成したCLIのサンプルについて紹介します。

環境

  • Go: 1.17
  • go-redis: 8.11.4
  • cobra: 1.3.0

cobraコマンドの導入については、下記リンクを参考にしてください。 github.com

サブコマンドの作成

$ cobra init で初期設定を行い、$ cobra add [command] で任意のコマンドを追加することができます。

# 初期設定
$ cobra init
Your Cobra application is ready at
/Users/example/workspace/tutorial/go-cobra

# サブコマンドを追加
$ cobra add get
get created at /Users/example/workspace/tutorial/go-cobra

これにより、下記のようなディレクトリ構成でいくつかファイルが生成されました。

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

1 directory, 6 files

データ取得

package cmd

import (
    "context"
    "fmt"
    "log"

    "github.com/go-redis/redis/v8"
    "github.com/spf13/cobra"
)

var getCmd = &cobra.Command{
    Use:   "get",
    Short: "get the value of a key",
    Long:  "get the value of a key",
    Run: func(cmd *cobra.Command, args []string) {
        key, err := cmd.Flags().GetString("key")
        if err != nil {
            log.Fatal(err)
        }

        client := redis.NewClient(&redis.Options{
            Addr: "localhost:6379",
        })

        value, err := client.Get(context.Background(), key).Result()
        if err != nil {
            log.Fatal(err)
        }

        fmt.Print(value)
    },
}

func init() {
    rootCmd.AddCommand(getCmd)
    getCmd.Flags().StringP("key", "k", "", "cache key")
}

データ登録

package cmd

import (
    "context"
    "log"
    "time"

    "github.com/go-redis/redis/v8"
    "github.com/spf13/cobra"
)

var setCmd = &cobra.Command{
    Use:   "set",
    Short: "set the string value of a key",
    Long:  "set the string value of a key",
    Run: func(cmd *cobra.Command, args []string) {
        key, err := cmd.Flags().GetString("key")
        if err != nil {
            log.Fatal(err)
        }

        value, err := cmd.Flags().GetString("value")
        if err != nil {
            log.Fatal(err)
        }

        client := redis.NewClient(&redis.Options{
            Addr: "localhost:6379",
        })

        err = client.Set(context.Background(), key, value, time.Minute).Err()
        if err != nil {
            log.Fatal(err)
        }
    },
}

func init() {
    rootCmd.AddCommand(setCmd)
    setCmd.Flags().StringP("key", "k", "", "cache key")
    setCmd.Flags().StringP("value", "v", "", "cache value")
}

実行

バイナリファイルとして利用するため、まずはビルドした後に実行します。

# ビルド
$ go build

# データを登録
$ ./cache set --key 'item' --value 'test-value'

# データを取得
$ ./cache get --key 'item'
// test-value

作成したCLIを使用して、データの登録および取得ができることを確認できました 🎉

ロスコンパイル

開発環境はMacですがLinux環境で動作することを想定しています。 Goではクロスコンパイルができるため、Linuxt環境で動作するようにコンパイルしています。

$ GOOS=linux GOARCH=amd64 go build

おわりに

cobraの使い方と実際に作成したCLIのサンプルについて紹介しました。 実際に業務で使用するためには、ホストやポートの指定、タイムアウト、取得できなかったときの処理など考慮する必要があります。 cobraを使うことで、かんたんにコマンドを作成することができるため、今後も使っていきたいです!