24
6

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 3 years have passed since last update.

[Go]なぜsliceの空チェックで「nil」ではなく「長さ」でチェックするのか

Last updated at Posted at 2021-04-30

1. はじめに

Uber Go Style Guide: nil-is-a-valid-slice
Uberのスタイルガイドにある通り、sliceの空チェックは長さでチェックしなくてはいけません。

To check if a slice is empty, always use len(s) == 0. Do not check for nil.

Bad	
func isEmpty(s []string) bool {
  return s == nil
}

Good
func isEmpty(s []string) bool {
  return len(s) == 0
}

さて、なぜsliceの空チェックで「nil」ではなく「長さ」でチェックするのか、体で覚えているだけできちんと理解していなかったので、まとめてみます。

2. sliceを「長さ」でチェックする理由

理由は、sliceが空になり、nilにならない場合が発生する可能性があるため、「長さ」でチェックしないと漏れが発生するためです。

ポイントは、
・sliceを空で宣言しても宣言の仕方によってnil sliceかempty sliceになる
・nil sliceとempty sliceともにlenとcapが0
ということです

2-1. 空で宣言しても宣言の仕方によってnil sliceかempty sliceになる

空で宣言しても、宣言の仕方によってはnil sliceかempty sliceと違いが出てきてしまい、nilチェックでは以下のパターンでチェックが漏れてしまいます。

func main() {
	// nil slice
	// こう定義するとnilになる
	var nilSlice []int
	fmt.Println(nilSlice, len(nilSlice), cap(nilSlice))
	fmt.Printf("nilSlice: %s\n\n", isEmptyByNil(nilSlice))

	// empty slice
	// こう定義するとnilにはならず、lenとcapが0となる
	emptySlice := []int{}
	fmt.Println(emptySlice, len(emptySlice), cap(emptySlice))
	fmt.Printf("emptySlice: %s\n\n", isEmptyByNil(emptySlice))
}

func isEmptyByNil(intSlice []int) string {
	if intSlice == nil {
		return "nil!"
	} else {
		return "not nil!"
	}
}

// 実行結果
[] 0 0
nilSlice: nil!

[] 0 0
emptySlice: not nil!

Go Playgroud

2-2. nil sliceとempty sliceともにlenとcapが0

nil sliceとempty sliceともにlenとcapが0という性質を利用して、長さでチェックをすれば漏れが発生することはありません。

func main() {
	// こう定義するとnilになる
	var nilSlice []int
	fmt.Println(nilSlice, len(nilSlice), cap(nilSlice))
	fmt.Printf("nilSlice: %s\n\n", isEmptyByLen(nilSlice))

	// こう定義するとnilにはならず、lenとcapが0のスライスとなる
	emptySlice := []int{}
	fmt.Println(emptySlice, len(emptySlice), cap(emptySlice))
	fmt.Printf("emptySlice: %s\n\n", isEmptyByLen(emptySlice))
}

func isEmptyByLen(intSlice []int) string {
	if len(intSlice) == 0 {
		return "len is zero!"
	} else {
		return "len is not zero!"
	}
}

// 実行結果
[] 0 0
nilSlice: len is zero!

[] 0 0
emptySlice: len is zero!

Go Playgroud

参考

Uber Go Style Guide: nil-is-a-valid-slice
技術メモ: Golangのnil sliceとnil map

24
6
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
24
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?