0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Go 言語を学ぶAdvent Calendar 2023

Day 13

subcommandsで作るGo製cli

Posted at

Go製cliといえば

GoでCLIを作ると言えばglagやcobraが有名かと思います。ですが今回はあえてGoogle製のsubcommandsでcliを作ってみます。

google/subcommands

Google謹製のライブラリということで、使ってみるしかありません。
他のcliを作るライブラリよりも極めてシンプルなのがgihubから伺えます。
今回は引数に渡されたcsvファイルの中身を標準出力として表示するといったものを作成します。(catええやん...)

インストール

 go get github.com/google/subcommands

ファイル作成

$ touch main.go
$ mkdir cmd && touch cmd/open_csv.go

コマンド本体

サブコマンドの設定や、処理の本体をここに書いています。

open_csv.go
package cmd

import (
	"context"
	"encoding/csv"
	"flag"
	"fmt"
	"io"
	"os"
	"strings"

	"github.com/google/subcommands"
)

type ShowCSVContentCmd struct {
	show string
}

func (*ShowCSVContentCmd) Name() string     { return "show" } // サブコマンド名指定
func (*ShowCSVContentCmd) Synopsis() string { return "show args csv content to stdout." }
func (*ShowCSVContentCmd) Usage() string {
	return `show [-capitalize] <some text>:
	Show args csv content to stdout.
`
}

func (p *ShowCSVContentCmd) SetFlags(f *flag.FlagSet) {
}

func (p *ShowCSVContentCmd) Execute(_ context.Context, f *flag.FlagSet, _ ...interface{}) subcommands.ExitStatus {
	for _, arg := range f.Args() {
		file, err := os.Open(arg)
		if err != nil {
			fmt.Printf("Failed to open file: %v\n", err)
			return subcommands.ExitFailure
		}
		defer file.Close()

		reader := csv.NewReader(file)
		for {
			record, err := reader.Read()
			if err == io.EOF {
				break
			}
			if err != nil {
				fmt.Printf("Failed to read CSV record: %v\n", err)
				return subcommands.ExitFailure
			}
			fmt.Println(strings.Join(record, ","))
		}
	}
	return subcommands.ExitSuccess
}

main関数です。

main.go
package main

import (
	"context"
	"flag"
	"os"

	"github.com/google/subcommands"
	"github.com/shuyaeer/golang-subcommands/cmd"
)

func main() {
  subcommands.Register(subcommands.HelpCommand(), "")
  subcommands.Register(subcommands.FlagsCommand(), "")
  subcommands.Register(subcommands.CommandsCommand(), "")
  subcommands.Register(&cmd.ShowCSVContentCmd{}, "")

  flag.Parse()
  ctx := context.Background()
  os.Exit(int(subcommands.Execute(ctx)))
}

実行してみる

$ go build -o gocsvcat . # ビルド
$ ./gocsvcat help
Usage: gocsvcat <flags> <subcommand> <subcommand args>

Subcommands:
	commands         list all command names
	flags            describe all known top-level flags
	help             describe subcommands and their syntax
	show             show args csv content to stdout.

csvファイルを用意します。

sample.csv
 Name,Age,City
Alice,25,New York
Bob,30,Los Angeles
Charlie,35,Chicago
$ ./gocsvcat show ./sample.csv
Name,Age,City
Alice,25,New York
Bob,30,Los Angeles
Charlie,35,Chicago

良さそうです。
あとは./gocsvcatをPATHが通っている/usr/local/binなどに配置すれば、どこからでもこのコマンドが使えるようになりますね。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?