2016-10-07 8 views
4

スライスのスライスをアンパックして、それらを可変長関数の引数として送信することに興味があります。我々はそれが動作するインタフェースのスライスに渡すためにwan't場合、我々はそれを解凍するかどうスライスのスライスを展開する

func unpack(args ...interface{}) 

、それは問題ではない:

のは、我々は可変引数のパラメータを持つ関数があるとしましょう

slice := []interface{}{1,2,3} 
unpack(slice) // works 
unpack(slice...) // works 

スライススライスがあると面倒です。ここでコンパイラは、私たちが解凍バージョンを渡すことはできません:

sliceOfSlices := [][]interface{}{ 
    []interface{}{1,2}, 
    []interface{}{101,102}, 
} 
unpack(sliceOfSlices) // works 
unpack(sliceOfSlices...) // compiler error 

エラーは言う:

タイプ[]インターフェース{としてsliceOfSlices(タイプ[] []インターフェイス{})を使用することができません} in unpackの引数

私は明確に[]interface{}型を関数に渡すことができるので、なぜこのようなことが起こるのかわかりません。どのようにして解凍された内容を解凍してsliceOfSlicesの引数として解凍することができますか?

遊び場の例は:https://play.golang.org/p/O3AYba8h4i

答えて

5

これはSpec: Passing arguments to ... parametersに覆われている。

fタイプ...Tの最後のパラメータpと可変長である場合、fpのタイプ[]Tを入力することと等価です。

...

最後の引数は、スライスタイプ[]Tに割り当てている場合は、引数が...が続いているならば、それは...Tパラメータの値としてそのまま渡すことができます。この場合、新しいスライスは作成されません。

短い中のSO

(タイプ[][]interface{}である)sliceOfSlicesは(proof on Playground)(タイプ[]interface{}である)argsに割り当てることができないので、それはコンパイル時エラーです。あなたの最初の例で

あなたがunpack(slice)を行い、unpack()interface{}の値は、したがって、sliceは(タイプ[]interface{}である)新しいinterface{}値に包まれることを期待するので、および:ロングで

それは単一引数として渡されます。

unpack(slice...)を実行すると、別の値としてsliceのすべての値がunpack()に渡されます。 sliceのタイプが[]interface{}であるため、これは可能です。これは、可変パラメータのタイプ(args ...interface{})と一致します。 2番目の例では

あなたがunpack(sliceOfSlices)を行う際に、再び、sliceOfSlices新しいinterface{}値で包み、単一の引数として渡されます。 ([][]interface{}です)sliceOfSlices

しかし、あなたはunpack()sliceOfSlicesの各要素を通過したいですunpack(sliceOfSlices...)を試みるが、タイプは、それゆえ、コンパイル時エラーを可変引数パラメータの型と一致していません。

unpack()からsliceOfSlicesを渡すための唯一の方法は、「爆発」の要素を、その種類[]interface{}でなければならない新しいスライスを作成コピーすることで、あなたは...を使用して、それを渡すことができます。

例:

var sliceOfSlices2 []interface{} 
for _, v := range sliceOfSlices { 
    sliceOfSlices2 = append(sliceOfSlices2, v) 
} 

unpack(sliceOfSlices2...) 

Go Playground上でそれを試してみてください。

のは、引数の数を確認するには、次のunpack()機能を使用してみましょう:

func unpack(args ...interface{}) { 
    fmt.Println(len(args)) 
} 

は(と私の新しいスライスを作成して)あなたの例を実行すると、出力は次のようになります。

...せずに証明
1 
3 
1 
2 

単一の引数のみが渡され(interface{}にラップされます)、...を使用すると、すべての要素が別々に渡されます。

このテストはGo Playgroundで試してみてください。

関連する問題