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?

More than 5 years have passed since last update.

flagパッケージを利用しているときに、オプションの値をスライスで受け取りたい / 同じオプションを複数回指定し、その値をすべてスライスに詰めたい

Posted at

Go言語のflagパッケージを利用して、コマンドラインツールを作成していると、オプションの値をSliceで受け取りたい場合があります。たとえば「同じオプションを複数回指定し、その値をすべてスライスに詰めたい」という場合、どのように実装すればよいでしょうか?

答えだけ先に述べておくと、flag.Valueインターフェースを実装し、パース時にはflag.Varを呼び出します。

今回は一例を示すにあたって、divコマンドを作成してみます。divコマンドは標準入力から数値が与えられると、-dオプションで与えられた数値で割り切れるかどうかを確認し、割り切れる場合は標準入力の値をそのまま標準出力に出力するというものです。ここでは-dオプションは複数回指定でき、複数回指定した場合は、1つでも割り切ることができればOKということにします。

動作イメージは次の通りです。ここでは1から15までの数値のうち、3または5で割り切れるものを出力しています。

$ seq 15 | ./div -d 3 -d 5
3
5
6
9
10
12
15

divコマンドの実装例は次の通りになります。

package main

import (
	"bufio"
	"flag"
	"fmt"
	"os"
	"strconv"
)

type Divisors []int

func (ds *Divisors) String() string {
	return fmt.Sprintf("%v", *ds)
}

func (ds *Divisors) Set(s string) error {
	d, err := strconv.Atoi(s)
	if err != nil {
		return err
	}
	*ds = append(*ds, d)
	return nil
}

func main() {
	var divisors Divisors
	flag.Var(&divisors, "d", "除数を指定してください")
	flag.Parse()

	stdin := bufio.NewScanner(os.Stdin)
	for stdin.Scan() {
		// 標準入力から1行読み込み、整数に変換。
		// 変換できない場合は理由を標準エラー出力に出力し、その行はスキップ
		line := stdin.Text()
		dividend, err := strconv.Atoi(line)
		if err != nil {
			fmt.Fprintln(os.Stderr, err)
			continue
		}

		// 標準入力から読み込んだ整数が、dオプションから取得した整数で割り切れるかどうかを検査。
		// 割り切れた場合は標準入力から読み込んだ値を標準出力に出力する。
		for _, divisor := range divisors {
			if dividend%divisor == 0 {
				fmt.Fprintln(os.Stdout, line)
				break
			}
		}
	}
}

ここではDivisors型(実体はintスライス)を作成、flag.Valueインターフェースの関数String()Set()をそれぞれ実装しています。パース時にflag.Var関数を呼び出すと、Divisors型(実体はintスライス)に-dオプションの値が格納されることが分かります。

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?