Go で 2つのスライスを連結する

Suraj Joshi 2023年1月30日
  1. スライスの宣言
  2. スライスの連結
  3. Go の append() 関数
Go で 2つのスライスを連結する

Go では、slice は同じデータ型の複数の要素を格納する動的データ構造です。それらは、配列の時点でインデックス付けされている可変サイズの配列と考えることもできますが、サイズを変更できるため、サイズは固定されていません。スライスは本質的に動的なので、append 関数を使用して 2つ以上のスライスをスライスまたは連結するために新しい要素を追加できます。

スライスの宣言

Slices の宣言は配列に似ていますが、サイズは指定されていません。

package main

import "fmt"

func main() {
    var Slice1 = []int{1, 2, 3, 4}
    fmt.Printf("Length of Slice: %v\n",len(Slice1))
    fmt.Printf("First Element: %v\n",Slice1[0])
    fmt.Printf("Second Element: %v\n",Slice1[1])
    fmt.Printf("Third Element: %v\n",Slice1[2])
    fmt.Printf("Fourth Element: %v\n",Slice1[3])

}

出力:

Length of Slice: 4
First Element: 1
Second Element: 2
Third Element: 3
Fourth Element: 4

スライスの連結

組み込みの append() 関数を使用して、2つ以上のスライスをリストまたは連結する要素を追加します。十分な容量がある場合、宛先は新しい要素に対応するように再スライスされます。十分な容量がない場合は、新しい基盤が割り当てられ、コンテンツがコピーされます。最後に、append() 関数は更新されたスライスを返します。

スライスに単一の要素を追加する

package main

import "fmt"

func main() {
    var slice_1 = []int{1, 2}
    slice_2 := append(slice_1, 3)  
    fmt.Printf("slice_1: %v\n", slice_1)
    fmt.Printf("slice_2: %v\n", slice_2)

}

出力:

slice_1: [1 2]
slice_2: [1 2 3]

複数の要素をスライスに追加する

package main

import "fmt"

func main() {
    var slice_1 = []int{1, 2}
    slice_2 := append(slice_1, 3)
    slice_3 := append(slice_2, 4,5,6)   
    fmt.Printf("slice_3: %v\n", slice_3)

}

出力:

slice_3: [1 2 3 4 5 6]

2つのスライスを連結する

package main

import "fmt"

func main() {
    var slice_3 = []int{1, 2, 3, 4, 5, 6}
    var slice_4 = []int{7,8}
    
    slice_5 := append(slice_3,slice_4...) 
    fmt.Printf("slice_4: %v\n", slice_4)
    fmt.Printf("slice_5: %v\n", slice_5)

}

出力:

slice_4: [7 8]
slice_5: [1 2 3 4 5 6 7 8]

Go で 2つのスライスを連結する際に注意すべき重要な点は、append() は他の可変関数と同様に可変関数であるため、slice_4 の後に ... が必須であることです。... を使用すると、スライスから関数に複数の引数を渡すことができます。ここで、append 関数は、slice_4 の各要素に対して再帰的に呼び出されます。

文字列をバイトスライスに追加する

var slice []byte = append([]byte("abc "), "def"...)
fmt.Printf("slice: %v\n", slice)

出力:

slice: [97 98 99 32 100 101 102]

ここで、文字は、文字の ASCII 値を表す 3 バイトを使用して UTF-8 でエンコードされます。スライスバイトは、次のように文字列に戻すことができます。

slice_str := string(slice)
fmt.Printf("String: %v\n", slice_str)

出力:

Slice: abc def

Go の append() 関数

append() 組み込み関数はスライスを受け取り、すべての要素を入力スライスの最後に追加して、最後に連結されたスライスを返します。デスティネーションスライスに十分な容量がある場合、追加された新しい要素に対応するために、スライスが再スライスされます。ただし、宛先に十分な容量がない場合、新しい配列が作成され、既存のスライスに存在する要素が新しい配列にコピーされ、最後に関数によって新しい配列が返されます。

package main

import "fmt"

func main() {

    slice_1 := []int{0, 1, 2}
    fmt.Println("slice_1 : ", slice_1)
    fmt.Println("Capacity of slice_1: ", cap(slice_1))

    res_1 := append(slice_1, 3)
    fmt.Println("res_1 : ", res_1)
    fmt.Println("Capacity of res_1: ", cap(res_1))

    slice_2 := make([]int, 3, 5)  //Create slice_1 with length 3 and capacity 5
    copy(slice_2, []int{0, 1, 2}) //Copy elements into slice_1
    fmt.Println("slice_2 : ", slice_2)
    fmt.Println("Capacity of slice_2: ", cap(slice_2))

    res_2 := append(slice_2, 3)
    fmt.Println("res_2 : ", res_2)
    fmt.Println("Capacity of res_2: ", cap(res_2))

}

出力:

slice_1 :  [0 1 2]
Capacity of slice_1:  3
res_1 :  [0 1 2 3]
Capacity of res_1:  6
slice_2 :  [0 1 2]
Capacity of slice_2:  5
res_2 :  [0 1 2 3]
Capacity of res_2:  5

ここで、slice_1 には新しい要素を追加する十分な容量がないため、容量 6 の新しいスライスが作成され、既存のスライスのすべての要素が新しく作成されたスライスにコピーされます。

ただし、slice_2 には新しい要素を追加する十分な容量があるため、要素は既存のスライスに追加されます。

著者: Suraj Joshi
Suraj Joshi avatar Suraj Joshi avatar

Suraj Joshi is a backend software engineer at Matrice.ai.

LinkedIn

関連記事 - Go Slice