Go slice의 nil

박재훈·2023년 3월 22일
0

GO

목록 보기
14/19

Go에서는 타입이 있는 nil과 타입이 없는 nil이 있다.
이전 게시글에서 interface((*struct)(nil))nil과 다르다는 것을 확인했다.
좀 더 찾아보니 슬라이스의 nil은 취급이 조금 다르다고 한다.

빈 슬라이스를 정의하는 방법은 보통 아래처럼 3가지가 있다.

var slice1 []int
slice2 := []int{}
slice3 := make([]int, 0)

이 중 첫번째는 var slice1 []int = nil과 동일하다.

먼저 nil인지 아닌지 확인을 해보도록 하자.

fmt.Println(slice1 == nil, slice2 == nil, slice3 == nil)

위 코드의 결과는 true false false이다. slice1은 확실히 nil이다. 그렇다면 이걸 참조하려고 하면 에러가 나지 않을까?

var slice1 []int
fmt.Println(slice1, len(slice1), cap(slice1))

slice1 = append(slice1, 10)
fmt.Println(slice1, len(slice1), cap(slice1))

// [] 0 0
// [10] 1 1

잘 작동한다. 슬라이스는 nil이어도 이용하는데 딱히 문제가 없다. 그럼 영향이 아예 없는 걸까?

serialized1, _ := json.Marshal(slice1)
serialized1, _ := json.Marshal(slice2)
serialized1, _ := json.Marshal(slice3)

// null
// []
// []

JSON으로 직렬화 했더니 slice1null이 되었다. 이것 외에는 크게 차이가 없다. API를 다룰 때 정도만 유의하면 될 것 같다.
Uber Go Style Guide에서는 nil 슬라이스는 유효하지만 직렬화와 같은 특정 상황에서는 차이가 나타난다고 한다.

그렇다면 함수 가변인자에서는 어떨까?

func F(i ...int) {
	fmt.Println(i == nil)
}

func main() {
	F()
	F(1)
}

// true
// false

기본적으로 값이 들어가지 않은 가변인자는 nil로 취급된다.

profile
코딩 좋아합니다

0개의 댓글