Goでは、関数は関数定義のパラメーターリストで指定されたタイプの引数のみを受け入れることができます。可変個引数パラメータ言語機能はそれを少し複雑にしますが、明確に定義されたルールに従います。
の関数シグネチャfmt.Println
は次のとおりです。
func Println(a ...interface{}) (n int, err error)
パー言語仕様、
関数シグニチャの最後の入力パラメータには、接頭辞...が付いた型があります。このようなパラメータを持つ関数は可変個引数と呼ばれ、そのパラメータに対して0個以上の引数を指定して呼び出すことができます。
これはPrintln
、interface{}
型の引数のリストを渡すことができることを意味します。すべての型が空のインターフェイスを実装しているため、任意の型の引数のリストを渡すことができます。これPrintln(1, "one", true)
により、たとえば、エラーなしで呼び出すことができます。言語仕様の「...パラメータへの引数の受け渡し」セクションを参照してください。
渡される値は、タイプ[] Tの新しいスライスであり、新しい基になる配列があり、その連続する要素は実際の引数であり、すべてTに割り当てることができる必要があります。
問題を引き起こしている部分は、仕様の直後です。
最後の引数がスライスタイプ[] Tに割り当て可能である場合、引数の後に...が続くと、... Tパラメータの値として変更されずに渡される可能性があります。この場合、新しいスライスは作成されません。
flag.Args()
タイプ[]string
です。以来T
ではPrintln
あるinterface{}
、[]T
です[]interface{}
。したがって、問題は、文字列スライス値がインターフェイススライスタイプの変数に割り当て可能かどうかにあります。割り当てを試みることで、goコードでそれを簡単にテストできます。次に例を示します。
s := []string{}
var i []interface{}
i = s
このような割り当てを試みると、コンパイラは次のエラーメッセージを出力します。
cannot use s (type []string) as type []interface {} in assignment
そのため、文字列スライスの後の省略記号を引数として使用することはできません。 fmt.Println
。これはバグではなく、意図したとおりに機能しています。
あなたが印刷できる方法はたくさん残っていflag.Args()
てPrintln
などは、
fmt.Println(flag.Args())
(fmtパッケージのドキュメント[elem0 elem1 ...]
ごとに、として出力されます)
または
fmt.Println(strings.Join(flag.Args(), ` `)
(それぞれが単一のスペースで区切られた文字列スライス要素を出力します)たとえば、文字列区切り文字を使用して文字列パッケージの結合関数を使用します。
go run test.go some test flags
)をいじっていましたが、flags.Args()...
justに変更すると機能するようでしたflag.Args()
(出力は[some test flags]
、改行が続きます。実際のフラグの登録でも機能するようです)。理由を理解するふりをしないでください、そしてスティーブンの答えはとにかくはるかに有益です:)