Go에서 nil이지만 nil이 아닌 경우

박재훈·2023년 3월 21일
1

GO

목록 보기
13/19

Go에서 nil인데 nil이 아닌 경우가 있다.
인터페이스 구현체의 포인터를 정의한 뒤 nil로 초기화 하고 그 인터페이스 타입으로 리턴한 걸 받으면 된다.
말로 하면 뭔소린지 잘 이해가 안가니 코드로 하면...

type Interface interface {
	Sample()
}

먼저 위처럼 인터페이스를 하나 정의한다. 이 인터페이스는 Sample()이라는 메소드를 가지고 있다.

type Structure struct{}

func (*Structure) Sample() {}

그리고 구조체를 하나 정의한 뒤 위의 인터페이스(Interface)를 구현한다.

func Test() Interface {
	var s *Structure = nil
	return s
}

이제 Interface 타입을 리턴하는 함수 Test()를 만들고, 그 안에서 Structure 포인터 객체를 리턴한다.
이때 반환하는 객체는 nil로 초기화 되어 있다.

t := Test()
fmt.Println(t)
fmt.Println(t == nil)

// <nil>
// false

테스트 해보기 위해 위와 같은 코드를 짰다.
첫번째 print에서는 <nil>이 나왔는데, 두번째 print에서는 false가 나왔다.
분명 nil끼리 비교했을텐데 다르다고 나온다.

t := Test()
fmt.Printf("%#v\n", t)
fmt.Printf("%#v\n", nil)

// (*main.Structure)(nil)
// <nil>

보다 자세한 비교를 위해 출력 방식을 바꿔보았더니 추가적인 확인이 가능했다. 둘은 엄밀히는 다른 nil이었던 것이다.
t는 타입은 지정이 되어 있었으나 그 값이 nil인 것이고, 비교하려던 nil은 그냥 전부 nil인 것이다.
마치 자바스크립트의 nullundefined 같은 관계였던 것이다.

var i Interface
fmt.Printf("%#v\n", i)
fmt.Println(i == nil)

// <nil>
// true

참고로 위처럼 그냥 인터페이스 객체 만들면 제로값은 nil이 된다.

그렇다면 이게 nil인지 아닌지를 코드 상에서 어떻게 파악하는가?
reflect를 이용하면 된다.

fmt.Println(reflect.ValueOf(t).IsNil())	// true

이러면 제대로 확인이 가능하긴 하다.

profile
코딩 좋아합니다

2개의 댓글

comment-user-thumbnail
2023년 4월 21일

좋네요 이거 땜에 구조체를 value로 받은 다음 인터페이스 변환해서 쓰기로 했어요

1개의 답글