配列とは違う!スライスを操作してみよう。Go言語ならではです

Go言語
この記事は約12分で読めます。
Go初学者
Go初学者

Go言語のスライスで要素を追加したり、メモリを確保する方法を知りたいな。

この記事ではGo言語のスライス操作を理解できます!
  • append関数を使ってスライスの要素を追加する
  • for文を使ってスライスの値を取り出す
  • make関数を使ってスライスのメモリを割り当てる
    1. len関数で要素数を確認
    2. cap関数で容量を確認
  • make関数の注意点

今回はスライスの要素を追加したり、スライスにメモリを割り当てる操作を行っていきます。

スライスの宣言に関しては、下記の記事を参考にしてください。

もりぴ
この記事を書いた人

XHTML1.0時代にHTML&CSSを勉強した経験あり。無趣味だった私が2020年5月からプログラミング学習を開始し現在も挫折せずに趣味で学習を楽しんでいる51歳。プログラミングの楽しさをブログを通してお伝えしていきます。

もりぴをフォローする

【Go言語のスライス操作】append関数でスライスの要素を追加しよう

Go言語では、スライスに要素を追加する時は append() 関数を使用します。

スライス名 = append(スライス名, 追加する要素の値1, …)

では、プログラムで確認してみましょう。

// スライスの操作
package main

import "fmt"

func main() {
    // スライスを宣言
    num := []int{1, 2, 3}
    fmt.Println(num)

    // append関数
    // スライスの最後に要素を追加する
    num = append(num, 4)
    fmt.Println(num)
}
// 出力結果
$ go run main.go 
[1 2 3]  // スライスを初期化した時の出力
[1 2 3 4]  // スライスにappend関数で要素を追加した時の出力

上記のプログラムでは要素をひとつだけ追加していますが、複数同時に追加することができます。

// スライスの操作
package main

import "fmt"

func main() {
    // スライスを宣言
    num := []int{1, 2, 3}
    fmt.Println(num)

    // append関数
    // スライスの最後に要素を追加する
    num = append(num, 4)
    fmt.Println(num)

    // appendは複数渡すことができる
    num = append(num, 5, 6, 7, 8, 9, 10)
    fmt.Println(num)
}
// 出力結果
$ go run main.go 
[1 2 3]
[1 2 3 4]
[1 2 3 4 5 6 7 8 9 10]  // 要素を複数渡した出力
もりぴ
もりぴ

スライスの方が配列よりも操作に柔軟性がありますね。

【Go言語のスライス操作】for文を使ってスライスの値を取得しよう

for文を使ってスライスの値を取得しましょう。

基本的なfor文を用いた方法とrangeを使った方法の2種類です。

基本的なfor文を使ったスライスの値の取得

// スライスの値をfor文で取得する
package main

import "fmt"

func main() {
    var sl []string = []string{"Golang", "Python", "C言語"}
    fmt.Println(sl)

    // for文の出力
    for i := 0; i < len(sl); i++ {
	fmt.Println(sl[i])
    }
}
// 出力結果
$ go run main.go
[Golang Python C言語]
Golang
Python
C言語

rangeを使ってスライスから値を取得(インデックスと値の両方)

// rangeを使ってスライスから値を取得(インデックスと値の両方)
package main

import "fmt"

func main() {
    var sl []string = []string{"Golang", "Python", "C言語"}
    fmt.Println(sl)

    // rangeでスライスの値を取得する
    for i, v := range sl {
	fmt.Println(i, v)
    }
}
// 出力結果
$ go run main.go
[Golang Python C言語]
0 Golang
1 Python
2 C言語

rangeを使ってスライスから値を取得(値のみ取得)

rangeを使って値のみ取得する場合は、インデックス番号の変数部分を _ にする必要があります。

// rangeを使ってスライスから値を取得(値のみ取得)
package main

import "fmt"

func main() {
    var sl []string = []string{"Golang", "Python", "C言語"}
    fmt.Println(sl)

    // インデックス番号不使用の場合
    for _, v := range sl {
	fmt.Println(v)
    }
}
// 出力結果
$ go run main.go
[Golang Python C言語]
Golang
Python
C言語

rangeを使ってスライスから値を取得(インデックス番号のみ取得)

// rangeを使ってスライスから値を取得(インデックス番号のみ取得)
package main

import "fmt"

func main() {
    var sl []string = []string{"Golang", "Python", "C言語"}
    fmt.Println(sl)

    // インデックス番号のみ取得する場合
    for i := range sl {
	fmt.Println(i)
    }
}
// 出力結果
$ go run main.go
[Golang Python C言語]
0
1
2

【Go言語のスライス操作】make関数でスライスのメモリを割り当てよう

Go言語・入門編の学習ではメモリ容量を意識しなくてもいいのですが、メモリの制限が厳しい環境で必要になるので覚えておきましょう。

スライスのメモリを割り当てるのに使用するのが make() 関数です。

スライス名 := make([]型, 要素数, 容量)

// make関数でスライスのメモリを割り当て
package main

import "fmt"

func main() {
    // make関数で第一引数に要素数を指定
    num2 := make([]int, 5)
    // num2を出力する
    fmt.Println(num2)
}
// 出力結果
$ go run main.go
[0 0 0 0 0]

make関数で生成したスライスに値を代入

上記のプログラムを元に値を代入してみましょう。

// make関数でスライスのメモリを割り当て
package main

import "fmt"

func main() {
    // make関数で第一引数に要素数を指定
    num2 := make([]int, 5)
    // num2を出力する
    fmt.Println(num2)

    // 値を代入
    num2[0] = 100
    fmt.Println(num2)
}
// 出力結果
$ go run main.go
[0 0 0 0 0]
[100 0 0 0 0]

num2[0]100 が代入されていることが確認できます。

このプログラムでは、 make() に要素数は指定していますが容量は指定していません。

では、 num2 の要素数と容量は現在どうなっているのでしょうか?

len()関数とcap()関数について

要素数を調べる関数が len() 関数で容量を調べる関数が cap() 関数です。

では、先程のプログラムを用いて要素数と容量を確認してみましょう。

// make関数でスライスのメモリを割り当て
package main

import "fmt"

func main() {
    // make関数で第1引数に要素数を指定
    num2 := make([]int, 5)
    // num2を出力する
    fmt.Println(num2)

    // len関数
    // 要素数を調べる
    fmt.Println("要素数は", len(num2), "です。")

    // cap関数
    // スライスのメモリ容量を調べる
    fmt.Println("容量は", cap(num2), "です。")
}
// 出力結果
$ go run main.go
[0 0 0 0 0]
要素数は 5 です。
容量は 5 です。

上記のプログラムでは要素数を 5 に指定して容量は指定していません。

この場合、要素数と同じだけの容量が確保されているのが確認できます。

では、make関数で要素数と容量の両方を指定してみましょう。

// make関数で指定した要素数より多く要素が追加
package main

import "fmt"

func main() {
    // 要素数と容量をmake関数で指定する
    num3 := make([]int, 5, 10)
    fmt.Println(num3)

    fmt.Println("要素数は", len(num3), "です。")
    fmt.Println("容量は", cap(num3), "です。")
}
// 出力結果
$ go run main.go
[0 0 0 0 0]
要素数は 5 です。
容量は 10 です。

make関数で指定した通りに要素数と容量が指定できました。

make関数で指定した要素数より多く要素が追加できる

スライスの特徴として要素数が追加できることでした。

make関数では要素数を指定できますが、それ以上に要素が追加できます。

// make関数で指定した要素数より多く要素が追加
package main

import "fmt"

func main() {
    // 要素数と容量をmake関数で指定する
    num3 := make([]int, 5, 10)
    fmt.Println(num3)

    // append関数で要素を追加する
    num3 = append(num3, 1, 2, 3, 4, 5)
    fmt.Println(num3)
    fmt.Println("要素数は", len(num3), "です。")
    fmt.Println("容量は", cap(num3), "です。")
}
// 出力結果
$ go run main.go
[0 0 0 0 0]
[0 0 0 0 0 1 2 3 4 5]
要素数は 10 です。
容量は 10 です。

make関数で要素数 5 で作成したスライスに要素を追加できていることが確認できます。

ただ、これがmake関数での注意点にもなるのです。

【Go言語のスライス操作】make関数での注意点

make関数の注意点に触れる前に、上記のプログラムを利用してさらに要素を追加してみましょう。

// make関数での注意点
package main

import "fmt"

func main() {
    // 要素数と容量をmake関数で指定する
    num3 := make([]int, 5, 10)
    fmt.Println(num3)

    // append関数で要素を追加する
    num3 = append(num3, 1, 2, 3, 4, 5)
    fmt.Println(num3)
    fmt.Println("要素数は", len(num3), "です。")
    fmt.Println("容量は", cap(num3), "です。")

    // さらにappend関数で要素を追加する
    num3 = append(num3, 1, 2, 3, 4, 5)
    fmt.Println(num3)
    fmt.Println("要素数は", len(num3), "です。")
    fmt.Println("容量は", cap(num3), "です。")
}
// 出力結果
$ go run main.go
[0 0 0 0 0]
[0 0 0 0 0 1 2 3 4 5]
要素数は 10 です。
容量は 10 です。
[0 0 0 0 0 1 2 3 4 5 1 2 3 4 5]
要素数は 15 です。
容量は 20 です。  // ここが注意点!

num3 は、最初に要素数 5 容量 10 でスライスを作成しました。

指定した容量を超えた要素数を追加すると、容量が倍の量が確保されているのが確認できます。

これがmake関数での注意点で、メモリを割り当ててメモリを無駄なく使用するためにmake関数で作成したスライスですが、使い方によっては無駄なメモリを消費してしまいます。

CHECK POINT

これがmake関数での注意点で、メモリを割り当ててメモリを無駄なく使用するためにmake関数で作成したスライスですが、使い方によっては無駄なメモリを消費してしまいます。

メモリの使用制限が厳しいプログラム開発では、make関数によるスライスの作成には十分注意が必要となります。

もりぴ
もりぴ

Go言語入門の学習段階では、あまり気にしなくても大丈夫です。

【まとめ】Go言語のスライスを操作してみよう!

今回は append() 関数によるスライスへの要素の追加と、make() 関数によるメモリの割り当てを行ってみました。

では、まとめに入りましょう。

Go言語のスライス操作 append関数とmake関数で押さえておくこと!
  • スライスに要素を追加するには append() を使用する
    スライス名 = append(スライス名, 追加する要素の値1, …)
  • スライスから値を取り出すにはfor文を活用する
  • スライスのメモリ割り当てをするには make() を使用する
    スライス名 := make([]型, 要素数, 容量)
  • スライスの要素数を調べるには len() を使用する
  • スライスの容量を調べるには cap() を使用する
  • make関数は使い方によっては、無駄なメモリ消費を起こす

以上となります。

特に append() 関数は使用することが多いので、きちんと理解しておきましょう。

スライスに関しては、まだまだお伝えしなければいけないことがあります…

無理なく学習を進めていきましょう!

comment

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