Open5

【Go】flagの使い方

shoetshoet

FlagSetの活用

set := flag.NewFlagSet("get", flag.ExitOnError)
st := set.String("st", "default", "set string")
it := set.Int("it", 0, "set int")

fmt.Println(*st)
fmt.Println(*it)
shoetshoet
fmt.Println(os.Args)
flag.Parse()
fmt.Println(flag.Args()) // os.Args[1:]が表示される
shoetshoet

入力されたサブコマンドに対応した処理を行う。

func main() {
	flag.Parse()
	getCmd := flag.NewFlagSet("get", flag.ExitOnError)
	setCmd := flag.NewFlagSet("set", flag.ExitOnError)
	reqCmd := flag.NewFlagSet("request", flag.ExitOnError)
	fmt.Println(getCmd.Name())

	cmds := []*flag.FlagSet{getCmd, setCmd, reqCmd}

	subCommands := os.Args[1:]

	for _, c := range cmds {
		if c.Name() == subCommands[0] {
			fmt.Printf("command is %s", subCommands[0])
		}
	}
}
shoetshoet

Commandインターフェースとコマンドごとの構造体を定義して、対応したサービス処理を実装する。

package main

import (
	"flag"
	"fmt"
	"os"
)

func main() {
	flag.Parse()

	cmds := []Command{
		NewGetCommand(),
		NewSetCommand(),
	}

	subCommands := os.Args[1:]

	for _, c := range cmds {
		if c.Name() == subCommands[0] {
			c.Service()
		}
	}
}

type Command interface {
	Name() string
	Service() error
}

type GetCommand struct {
	FlagSet *flag.FlagSet
}

func NewGetCommand() *GetCommand {
	cmd := flag.NewFlagSet("get", flag.ExitOnError)
	return &GetCommand{
		FlagSet: cmd,
	}
}

func (g *GetCommand) Name() string {
	return g.FlagSet.Name()
}
func (g *GetCommand) Service() error {
	fmt.Println("run get")
	return nil
}

type SetCommand struct {
	FlagSet *flag.FlagSet
}

func NewSetCommand() *SetCommand {
	cmd := flag.NewFlagSet("set", flag.ExitOnError)
	return &SetCommand{
		FlagSet: cmd,
	}
}

func (s *SetCommand) Name() string {
	return s.FlagSet.Name()
}
func (s *SetCommand) Service() error {
	fmt.Println("run set")
	return nil
}
shoetshoet

構造体を通してサブコマンド以降を引き渡す。

package main

import (
	"flag"
	"fmt"
	"log"
	"os"
)

func main() {
	getCmd := NewGetCommand()
	setCmd := NewSetCommand()
	cmds := []Command{getCmd, setCmd}

	if err := ExecSubCommand(cmds); err != nil {
		log.Fatal(err)
	}
}

func ExecSubCommand(cmds []Command) error {
	subCommands := os.Args[1:]
	for _, c := range cmds {
		if c.Name() == subCommands[0] {
			if err := c.Parse(); err != nil {
				return fmt.Errorf("failed flag parse: %v", err)
			}
			if err := c.RunCommand(); err != nil {
				return fmt.Errorf("failed execute command: %v", err)
			}
			break
		}
	}
	return nil
}

type Command interface {
	Name() string
	RunCommand() error
	Parse() error
}

type GetCommand struct {
	FlagSet *flag.FlagSet
	Key     *string
}

func NewGetCommand() *GetCommand {
	cmd := flag.NewFlagSet("get", flag.ExitOnError)
	key := cmd.String("key", "", "get key")
	return &GetCommand{
		FlagSet: cmd,
		Key:     key,
	}
}

func (g *GetCommand) Name() string {
	return g.FlagSet.Name()
}
func (g *GetCommand) RunCommand() error {
	fmt.Println("run get")
	fmt.Printf("set key: %s", *g.Key)
	return nil
}
func (g *GetCommand) Parse() error {
	return g.FlagSet.Parse(os.Args[2:])
}

type SetCommand struct {
	FlagSet *flag.FlagSet
	Key     *string
	Value   *string
}

func NewSetCommand() *SetCommand {
	cmd := flag.NewFlagSet("set", flag.ExitOnError)
	key := cmd.String("key", "", "set key")
	value := cmd.String("value", "", "set value")
	return &SetCommand{
		FlagSet: cmd,
		Key:     key,
		Value:   value,
	}
}

func (s *SetCommand) Name() string {
	return s.FlagSet.Name()
}
func (s *SetCommand) RunCommand() error {
	fmt.Println("executed set")
	fmt.Printf("set key: %s, value: %s", *s.Key, *s.Value)
	return nil
}
func (s *SetCommand) Parse() error {
	return s.FlagSet.Parse(os.Args[2:])
}