2
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?

More than 5 years have passed since last update.

Goのsliceでcapを指定した方が良いケース

Posted at

以前レビューしていたときに、capを指定した方が良い理由を説明したら分かりやすいと言っていただいたので、嬉しくなってQiitaにも書きます。

以下のように、全てのUserのうち特定のUserだけを取り出したい場合を想定します。

type User struct {
	ID int64
	Name string
	Status int8	// 0 -> InActive, 1 -> Activeとする
}

func main() {
	users := []*User{
		&User{
			ID: 0,
			Name: "user0",
			Status: 0,
		},
		&User{
			ID: 1,
			Name: "user1",
			Status: 1,
		},
		&User{
			ID: 2,
			Name: "user2",
			Status: 0,
		},
		...
	}
	
	
	// 1. activeUsers := []*User{}
	// 2. activeUsers := make([]*User, 0, len(users))
	// 1と2はどっちが良いか?
	
	for _, u := range users {
		// activeなユーザーだけ取り出したい
		if u.Status == 1 {
			activeUsers = append(activeUsers, u)
		}
	}	
}

activeUsersのの大きさはusersのlenよりも小さくなる可能性が高い(上記の例の場合は間違いなく小さい)ので、capを指定したらその分無駄な容量を確保するのではないか?という疑問を持っていたようです。

  • 1(capを指定しない)の場合
package main

import (
	"fmt"
)

func main() {
	l := []int{}

	for i := 0; i < 17; i++ {
		l = append(l, i)
		fmt.Println("len: ", len(l), ", cap: ", cap(l))
	}
}


-------------- result --------------

len:  1 , cap:  2
len:  2 , cap:  2
len:  3 , cap:  4
len:  4 , cap:  4
len:  5 , cap:  8
len:  6 , cap:  8
len:  7 , cap:  8
len:  8 , cap:  8
len:  9 , cap:  16
len:  10 , cap:  16
len:  11 , cap:  16
len:  12 , cap:  16
len:  13 , cap:  16
len:  14 , cap:  16
len:  15 , cap:  16
len:  16 , cap:  16
len:  17 , cap:  32

https://play.golang.org/p/-lxFdnmrz0z
capが足りなくなった場合に2倍のcapを確保するので、大きくなればなるほど無駄にメモリ確保する可能性が高い

  • 2(capを指定する)の場合
package main

import (
	"fmt"
)

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

	for i := 0; i < 17; i++ {
		l = append(l, i)
		fmt.Println("len: ", len(l), ", cap: ", cap(l))
	}
}


-------------- result --------------

len:  1 , cap:  20
len:  2 , cap:  20
len:  3 , cap:  20
len:  4 , cap:  20
len:  5 , cap:  20
len:  6 , cap:  20
len:  7 , cap:  20
len:  8 , cap:  20
len:  9 , cap:  20
len:  10 , cap:  20
len:  11 , cap:  20
len:  12 , cap:  20
len:  13 , cap:  20
len:  14 , cap:  20
len:  15 , cap:  20
len:  16 , cap:  20
len:  17 , cap:  20

https://play.golang.org/p/7Q1TW_CF2-A
実際のlenがcapに満たない場合でも、倍確保されるよりはメモリ使わないで済むし、確保するための処理が入らないのでより良い

ということで、こういう場合はcapを指定しましょう!

2
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
2
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?