スライス[1, 2]
とスライス[3, 4]
を結合しようとしています。 Goでこれを行うにはどうすればいいですか。
私は試した:
append([]int{1,2}, []int{3,4})
しかし:
cannot use []int literal (type []int) as type int in append
しかし、 ドキュメンテーション はこれが可能であることを示しているようですが、足りないものは何ですか?
slice = append(slice, anotherSlice...)
2番目のスライスの後にドットを追加します。
//---------------------------vvv
append([]int{1,2}, []int{3,4}...)
これは他の可変基数関数とまったく同じです。
func foo(is ...int) {
for i := 0; i < len(is); i++ {
fmt.Println(is[i])
}
}
func main() {
foo([]int{9,8,7,6,5}...)
}
可変関数
append
は、x
型のs
にゼロ個以上の値S
を追加し、スライス型でなければならず、結果として得られるスライスもS
型で返します。値x
は...T
型のパラメータに渡されます。ここでT
はS
の要素型であり、それぞれのパラメータ引き渡し規則が適用されます。特別な場合として、appendはstring
型の第2引数とそれに続く[]byte
の型...
に代入可能な第1引数も受け入れます。この形式は文字列のバイトを追加します。append(s S, x ...T) S // T is the element type of S s0 := []int{0, 0} s1 := append(s0, 2) // append a single element s1 == []int{0, 0, 2} s2 := append(s1, 3, 5, 7) // append multiple elements s2 == []int{0, 0, 2, 3, 5, 7} s3 := append(s2, s0...) // append a slice s3 == []int{0, 0, 2, 3, 5, 7, 0, 0}
f
が最終パラメータ型...T
の可変長である場合、関数内では引数は型[]T
のパラメータと同等です。f
が呼び出されるたびに、最後のパラメータに渡される引数は、連続する要素が実際の引数である[]T
型の新しいスライスです。これらはすべてT
型に代入可能である必要があります。スライスの長さは、したがって、最後のパラメータにバインドされた引数の数であり、コールサイトごとに異なります。
あなたの質問に対する答えは Goプログラミング言語仕様 の中の例s3 := append(s2, s0...)
です。例えば、
s := append([]int{1, 2}, []int{3, 4}...)
他の答えに反することは何もありませんが、 docs に簡単な説明があります。
func append
func append(slice []Type, elems ...Type) []Type
append組み込み関数はスライスの最後に要素を追加します。十分な容量がある場合は、新しい要素に対応するために宛先が再スライスされます。そうでない場合は、新しい基になる配列が割り当てられます。 Appendは更新されたスライスを返します。したがって、appendの結果をスライス自体を保持する変数に格納する必要があります。slice = append(slice, elem1, elem2) slice = append(slice, anotherSlice...)
特別な場合として、次のようにバイトスライスに文字列を追加することは正当です。
slice = append([]byte("hello "), "world"...)
宛先スライス(追加するスライス)に十分な容量がある場合、宛先を再スライスすることによりincrease追加可能な要素を収容できるようにするための長さ)。
これは、結果のスライスの長さを超える追加要素を持つ大きな配列またはスライスをスライスすることによって宛先が作成された場合、それらが上書きされる可能性があることを意味します。
例を示すには、次の例を参照してください。
a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)
x, y := a[:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))
x = append(x, y...)
fmt.Printf("x: %v\n", x)
fmt.Printf("a: %v\n", a)
出力( Go Playground で試してください):
a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 10
x: [1 2 3 4]
a: [1 2 3 4 0 0 0 0 0 0]
長さ10
の「バッキング」配列a
を作成しました。次に、このx
配列をスライスしてa
宛先スライスを作成し、複合リテラル[]int{3, 4}
を使用してy
スライスを作成します。ここでy
をx
に追加すると、結果は期待される[1 2 3 4]
になりますが、驚くべきことは、a
の容量が10
であり、これがx
を追加するのに十分なためですそれで、同じy
バッキング配列を使用するx
が再スライスされ、append()
はa
の要素をそこにコピーします。
これを避けたい場合は、 full slice expression の形式を使用できます。
a[low : high : max]
スライスを構築し、max - low
に設定することで、結果のスライスの容量も制御します。
変更された例を参照してください(唯一の違いは、x = a[:2:2]
:のようにy
を作成することです。
a := [10]int{1, 2}
fmt.Printf("a: %v\n", a)
x, y := a[:2:2], []int{3, 4}
fmt.Printf("x: %v, y: %v\n", x, y)
fmt.Printf("cap(x): %v\n", cap(x))
x = append(x, y...)
fmt.Printf("x: %v\n", x)
fmt.Printf("a: %v\n", a)
出力( Go Playground で試してください)
a: [1 2 0 0 0 0 0 0 0 0]
x: [1 2], y: [3 4]
cap(x): 2
x: [1 2 3 4]
a: [1 2 0 0 0 0 0 0 0 0]
ご覧のとおり、同じx
の結果が得られますが、x
の容量は「のみ」であるため、バッキング配列a
は変更されませんでした2
(完全なスライス式a[:2:2]
のおかげ)。したがって、追加を行うために、x
とx
とは異なるy
とa
の両方の要素を格納できる新しいバッキング配列が割り当てられます。
2つのスライスは標準のgolangライブラリのappend
メソッドを使って連結できます。これはvariadic
関数操作に似ています。だから私たちは...
を使う必要があります
package main
import (
"fmt"
)
func main() {
x := []int{1, 2, 3}
y := []int{4, 5, 6}
z := append([]int{}, append(x, y...)...)
fmt.Println(z)
}
上記のコードの出力は次のとおりです。[1 2 3 4 5 6]
append([]int{1,2}, []int{3,4}...)
は動作します。 ...
パラメータに引数を渡す.
f
が、タイプ...T
の最終パラメーターp
を使用して可変長である場合、f
内では、タイプp
はタイプ[]T
と同等です。
f
に実際の引数を指定せずにp
が呼び出された場合、p
に渡される値はnil
です。
それ以外の場合、渡される値は連続する要素が実際の引数であるすべてのT
に代入可能である必要がある新しい基底配列を持つタイプ[]T
の新しいスライスです。したがって、スライスの長さと容量はp
にバインドされている引数の数であり、呼び出しサイトごとに異なる可能性があります。
与えられた機能と呼び出し
func Greeting(prefix string, who ...string)
Greeting("nobody")
Greeting("hello:", "Joe", "Anna", "Eileen")