Golangのスライス(slice)について特徴や使い方を総まとめ

Golang

Golangのスライス(slice)とは

スライスはサイズ変更可能な配列であり、それを扱う際に非常に大きな柔軟性を提供します。

Golangにおいて配列(array)とは、サイズ変更が不可の配列であり、RubyやJavaScript等での「配列」とは異なる特徴があります。

なので、RubyやJavaScript等での「配列」はGolangではスライス(slice)ということになります。

スライス(slice)の定義・宣言

スライスは配列と同じように宣言されますが、その要素数には言及しません。

package main
 
func main() {
    var sampleSlice []string     // 文字列のスライス
}

スライス(slice)と配列(array)の違い

Golangにおける、スライスと配列の違いは以下の通りです

  • 配列は要素数が指定されて宣言された後、要素数を変更することができませんが、スライスは要素数を変更することができる。
  • スライスは参照型であるのに対し、配列は値型である。

Golangでスライスを作成する

スライスを作成する方法はいくつかあります。

sliceリテラル構文の使用

スライスリテラルは、スライスの初期化構文です。

以下は、スライスリテラルの構文を使用してスライスを作成する例です。

package main
 
import "fmt"
 
func main() {
    var stringSlice = []string{"I", "like", "banana"}
    fmt.Println(stringSlice)  // [I like banana]
}

配列からスライスを作成する

スライスは配列への参照を持っています。ですから、配列から作成することは難しくありません。

以下の書式だと配列からスライスを作成することができます。

配列[始まりのインデックス番号:終わりのインデックス番号]

上記の方法でスライスを作成する具体的なコード例は以下になります。

package main

import (
	"fmt"
)

func main() {
	var arr = [7]int{1, 2, 3, 4, 5, 6, 7}
	var arrSlice = arr[1:5]

	fmt.Println(arrSlice) // [2 3 4 5]
}

他のスライスからスライスを作成する

スライスは、そのスライスを切り取ることで、他のスライスから作成することができます。

package main

import "fmt"

func main() {
	var oddNumbers = [9]int{1, 3, 5, 7, 9, 11, 13, 15, 17}

	slice1 := oddNumbers[4:]
	fmt.Println(slice1) //  [9 11 13 15 17]

	slice2 := slice1[2:4]
	fmt.Println(slice2) //  [13 15]
}

make()関数でスライスを作成する

Goにはmake()という関数があり、これを使ってスライスを作成することもできます。これはスライスの種類、長さ、そしてそのスライスの容量を引数に受け取ります。

package main
 
import "fmt"
 
func main() {
    sampleSlice := make([]int, 6) // 要素数が6の数値のスライスを作成

    fmt.Println(sampleSlice) // [0 0 0 0 0 0]
}

len()関数とcap()関数

len()関数とcap()関数は、スライスの長さと容量を提供します。

両者の違いを理解するために、例を見てみましょう。

package main

import "fmt"

func main() {
	sampleSlice := []int{2, 4, 6, 8, 10}
	fmt.Println(len(sampleSlice), cap(sampleSlice)) // 5 5

	arr := [6]int{1, 2, 3, 4, 5, 6}
	arrSlice := arr[1:4]

  fmt.Println(arrSlice) // [2 3 4]
	fmt.Println(len(arrSlice), cap(arrSlice)) // 3 4
}

スライスのゼロ値

スライスのゼロ値はnilです。つまり、そのスライスのlengthはゼロになります。

package main
 
import "fmt"
 
func main() {
    sampleSlice := []int{}
    fmt.Println(len(sampleSlice), cap(sampleSlice)) // 0 0
}

スライス内の値を変更する

スライス内の値の変更は実に簡単です。

スライスに対してインデックスを指定してデータを割り当てるだけです。

package main

import "fmt"

func main() {
	sampleSlice := []int{1, 2, 3, 4}
	sampleSlice[1] = 0

	fmt.Println(sampleSlice) // [1 0 3 4]
}

スライスから値を削除する

スライス内のインデックスiの値を削除するには、インデックスiまでとi+1から末尾までの要素を単純に追加すればよいです。

package main

import "fmt"

func main() {
	sampleSlice := []int{1, 2, 3, 4, 5, 6, 7, 8}
	_ = append(sampleSlice[:3], sampleSlice[4:]...) // 三番目の要素を削除する

	fmt.Println(sampleSlice) // [1 2 3 5 6 7 8 8]
}

スライスを関数に渡す方法

スライスを関数に渡し、その内部で変更を加えた場合、その変更は外部でも利用できるようになります。この背景には、スライスが参照型であることがあります。

package main

import "fmt"

func main() {
	sampleSlice := []int{1, 2, 3, 4, 5}
	PrintSlice(sampleSlice) // [1 2 3 4 5]
}

func PrintSlice(slice []int) {
	fmt.Println(slice)
}

スライスの関数

スライスをさらに使いやすくするスライス関数があります。ここでは重要なものをいくつか紹介します。

package main

import "fmt"

func main() {
	s := []int{1, 2, 3, 4, 5}
	var s2 = make([]int, 5)

	s = append(s, 6, 7)

	fmt.Println(s) // [1 2 3 4 5 6 7]

	// 関数をコピー
	e := copy(s2, s)

	fmt.Println(s2, e) // [1 2 3 4 5] 5
}

スライスのスライス

本質的に多次元的なスライスを作成することができます。

package main
 
import "fmt"
 
func main() {
    numbers := [][]int{
        {1, 2, 3},
        {4, 5, 6},
        {7, 8, 9},     // カンマを忘れずに
    }
     
    fmt.Println(numbers)    // [[1 2 3] [4 5 6] [7 8 9]]
}

スライスの要素に対する繰り返し処理

スライスに対する反復処理は、for-rangeループを使用して行うことができます。単純なforループをlen関数と一緒に使うこともできます。以下はその方法である。

package main

import "fmt"

func main() {
	numbers := []int{1, 2, 3, 4, 5, 6, 7}

	for i, v := range numbers {
		fmt.Println(i, v)
	}
}

// 出力結果:
// 0 1
// 1 2
// 2 3
// 3 4
// 4 5
// 5 6
// 6 7

タイトルとURLをコピーしました