Golang의 nil과 interface nil의 재미있는 특징
Null은 일반적으로 존재하지 않는 값 또는 메모리 주소를 의미하며 언어에 따라 null
nil
nan
none
undefined
등 여러가지 형태로 표현됩니다. 다만 null이란 개념이 언어마다 특성과 철학, 표현하는 방식에 따라서 달라지기도 하는데요. 오늘은 golang에서의 null인 nil의 특성 하나를 살펴보려고 합니다.
zero value
먼저 zero value에 대해 알고가면 이해에 좋습니다. zero value는 초기값을 가지지 않고 변수를 만들었을 때 해당 변수가 가질 값을 의미합니다.
nil
nil은 pointer
, interface
, slice
, channel
, func
의 zero value 입니다.
그래서 아래와 같이 string 등의 zero value는 공백이지만, slice를 만들어서 확인해보면 nil을 zero value를 가집니다.
package main
import "fmt"
func main(){
var a string
fmt.Println(a)
// 아래 코드처럼 nil과 비교하면 에러가 발생합니다.
}
package main
import "fmt"
func main(){
var b []string
fmt.Println(b == nil)
}
Interface nil
아래 코드는 interface를 zero value로 만들고 nil인지 비교하는 코드인데, 어떤 결과가 나올까요?
package main
import (
"fmt"
)
type A struct {}
func makeNil() interface{} {
var a A
return a
}
func main() {
n := makeNil()
if n == nil {
fmt.Println("makeNil() is nil")
} else {
fmt.Println("makeNil() is not nil")
}
}
눈으로만 본다면 makeNil() is nil
가 나올 것 같지만, 실제론 아래 메시지가 출력됩니다.
makeNil() is not nil
이는 interface가 Type: Value,
와 같이 type을 저장하는 T
값과 value를 저장하는 V
2가지를 사용해서 데이터를 저장하는데 zero value로 인해 value 가 nil이 되어도 주소값을 저장해야하는 type은 nil을 줄 수 없기 때문에 nil이 아니게 됩니다.
그래서 아래와 같이 Typeof로 interface 를 찍어보면 nil이 아닌 main.A
가 찍힙니다.
func makeNil() interface{} {
var a A
fmt.Println(reflect.TypeOf(a))
return a
}
그래서 makeNil()
의 결과는 nil이 아니게 됩니다.
Conclusion
개발하다보면 충분히 실수할 수 있는 부분이라 잘 알아두고 있는게 좋을 것 같습니다 :D