Go언어 제네릭 인터페이스 타입 파라미터는 구조체 객체여야 한다

박재훈·2023년 1월 8일
0

GO

목록 보기
11/19

아래와 같은 코드가 있다.

type A interface {
	Test()
}

func F[T A]() T {
	return nil
}

인터페이스 A가 있으며, 함수 FA를 타입 파라미터로 갖는 제네릭 함수이다.
FA 타입 객체를 리턴할테니, 그리고 Go에서 인터페이스는 포인터로 되어 있으니 위처럼 T 타입을 리턴한다고 하고서 nil을 리턴하는 것은 아무런 문제가 없어 보인다.

cannot use nil as T value in return statement

그런데 위처럼 에러가 난다. 그럼 포인터도 아니란 얘기고, 인터페이스 객체도 아니란 얘긴가?

이상해서 A를 구현하는 구조체를 만든 뒤 그걸로 테스트를 해봤다.

type AA struct{}
func (*AA) Test() {}

// 1
func F[T A]() T {
    return &AA{}
}

// 2
func F[T A]() T {
    return AA{}
}

놀랍게도 위 1, 2번 모두 에러가 난다. 너무 이상하다, 그럼 T 타입을 아예 생성하고서 출력해보면 뭐가 나올까?

func F[T A]() T {
    return *new(T)
}

func main() {
	// 1. *AA 타입 이용하기
	fmt.Printf("%#v\n", F[*AA]()
    // 2. A 타입 이용하기
    fmt.Printf("%#v\n", F[A]())
}

// 결과
// 1. (*main.AA)(nil)
// 2. <nil>

어찌보면 당연한 결과이긴 한데, 잘 예상이 안간다.
그럼 인터페이스 타입으로 객체 생성 후 형변환 해서 리턴하면?

func F[T A]() T {
	var aa A = &AA{}
	return aa.(T)
}

func main() {
	fmt.Printf("%#v\n", F[A]()
}

// &main.AA{}

잘 나온다. 참 이상하다.
참고로 아래처럼 정의한 함수는 (당연히) 에러 없이 잘 된다.

func F[T A](t T) T {
	return t
}

결론

그래서 뭐 결론을 내보자면... 제네릭 타입을 인터페이스로 설정한 뒤 그 인터페이스를 구현한 구조체 객체를 생성해서 리턴하는 형태는 피해야 한다.

profile
코딩 좋아합니다

0개의 댓글