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?

golang のコマンドライン引数の定石

Last updated at Posted at 2025-08-12

はじめに

ここでは私が go 言語を書いているうちに定着したコマインドライン引数の定石を書きます。まず go言語の標準パッケージのコマインドライン引数処理は、python の argparse と比べて機能はかなり限られています。

  • long option, short option の区別がない
    --flag,-f のようにハイフンの数で long,short option を使い分けるという機能はありません。その代わりオプションは何文字でもよく、--flag-flag も同じとみなされます。
  • オプション引数は必ず位置引数の前
    ./cmd -a opt1 -b opt2 arg1 arg2 というコマンドを ./cmd arg1 arg2 -a opt1 -b opt2 とするとオプションを認識できなくなります。

python の argparse のようなことをしたかったら外部パッケージを使ってください。

定石

匿名 struct の変数 args を定義する

以下のようにします。

package main
import (
    "fmt"
    "os"
    "flag"
)

var args struct {
    opt1,opt2 string
    flag1 bool
}

定石2: flag.*Var 関数でオプション引数をセット

func main() {
    flag.StringVar(&args.opt1,"opt1","","option 1")
    flag.StringVar(&args.opt2,"opt2","","option 2")
    flag.BoolVar(&args.flag1,"flag1",false,"flag 1")
    flag.Parse()
}

定石2: 位置引数は flag.Args() で取得

以下の mainargs[0] に 1番目の位置引数、mainargs[1] に 2番目 ... というふうに入ります。ちなみに、os.Args にはフラグ処理をしないすべての引数が入っています。os.Argsflag.Args() を混同しないように!

func main() {
    ...
    flag.Parse()
    mainargs := flag.Args()
}

定石3: usage() 関数を用意

メインの説明を書きます。flag の説明は flag.PrintDefaults() を読んでやってもらいます。

func usage() {
    fmt.Fprintf(os.Stderr,"usage: %s [flags] [filein]\n",os.Args[0])
    flag.PrintDefaults()
}

そして main 関数のほうで flag.Usage = usage の文を加えてください。

全体像

package main
import (
    "fmt"
    "os"
    "flag"
)

var args struct {
    opt1,opt2 string
    flag1 bool
}

func usage() {
    fmt.Fprintf(os.Stderr,"usage: %s [flags] [filein]\n",os.Args[0])
    flag.PrintDefaults()
}

func main() {
    flag.Usage = usage
    flag.StringVar(&args.opt1,"opt1","","option 1")
    flag.StringVar(&args.opt2,"opt2","","option 2")
    flag.BoolVar(&args.flag1,"flag1",false,"flag 1")
    flag.Parse()
    if len(mainargs) < 1 {
        usage()
        os.Exit(1)
    }
    MyFunc(mainargs[0],args.opt1)
}

高段者向け

オプション引数をパースして構造体にしたり、複数回の同じオプション引数をリストにしたいとき flag.Var() が使えます。例えば mail -c cc1 -c cc2 -c cc3 という入力により [cc1,cc2,cc3] というリストにしたいときです。
まず type で格納するデータ型を作ります。go 言語 では[]string のような型でも type で新しい型として定義でき、メソッドを追加できます。これを使って新しい型を定義して、String() stringSet(string) error メソッドを定義します。するとflag.Var() でセットできるようになります。もちろん、もともと使う予定の既存の型にそれらのメソッドを追加してもよいです。

type cclist []string
func (cc *cclist) String() string {
    var s strings.Builder
    for _,c := range *cc {
        fmt.Fprintf(&s,"%s,",c)
    }
    return s.String()
}
func (cc *cclist) Set(s string) error {
    *c = append(*c,s)
}

このようにして

var args struct (
    cc cclist
)

func main() {
    ...
    flag.Var(&args.cc,"cc","cc. for multiple cc use flag repeatedly")
}

そうすると

mail -c cc1 -c cc2 -c cc3

としたら args.cc : []string{"cc1","cc2","cc3"} になります。

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?