0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

Goのスライスの挙動について調べた。

容量を超える要素を追加したときは、元の容量を2倍したスライスが作られる。

元のスライスをコピーして新しいスライスが作られるため、メモリ上のアドレスが異なる。

つまり、元のスライスの分だけ、余分にメモリを消費するということ。

package main

import "fmt"

func main() {
	s1 := make([]int, 1, 5)
	fmt.Println("Len:", len(s1), "Cap:", cap(s1)) // Len: 1 Cap: 5
	fmt.Printf("%p\n", s1)                        // 0xc00001a150

	// 容量を超える要素を追加
	s1 = append(s1, 1)
	s1 = append(s1, 2)
	s1 = append(s1, 3)
	s1 = append(s1, 4)
	s1 = append(s1, 5)
	fmt.Println("Len:", len(s1), "Cap:", cap(s1)) // Len: 6 Cap: 10
	fmt.Printf("%p\n", s1)                        // 0xc00001e050
}

ということは、下記のような場合、スライスのコピーが何度も繰り返され、メモリを消費する。

package main

import "fmt"

func main() {
	s1 := make([]int, 0)

	for i := 0; i < 10000; i++ {
		s1 = append(s1, i)
		fmt.Println("Len:", len(s1), "Cap:", cap(s1))
		fmt.Printf("%p\n", s1)
	}
}

なので、処理をする前に既にスライスの大きさが分かっているなら、長さか容量を指定してスライスを初期化しましょう。

package main

import "fmt"

func main() {
	s1 := make([]int, 0, 10000)

	for i := 0; i < 10000; i++ {
		s1 = append(s1, i)
		fmt.Println("Len:", len(s1), "Cap:", cap(s1))
		fmt.Printf("%p\n", s1)
	}
}

参考図書

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?