【Go 언어】interface 의 포인터로부터 메소드 호출할 수 없는 것은 왜?

결론



간결하게 말하면 「interface 를 가리키는 포인터는 interface 를 실장한 구조체의 포인터의 포인터가 되기 때문」입니다.
이것만으로는 잘 모르기 때문에 자세히 살펴 보겠습니다.

interface 의 포인터로부터 메소드 콜을 할 수 없다고는?



interface의 Mammal과 그것을 구현한 Human이라는 구조체를 생각해 봅시다.
type Mammal interface {
    GetAge() int
}

type Human struct {
    Age int
}

func (h *Human) GetAge() int {
    return h.Age
}

이 때, 다음과 같이 Mammal이라는 인터페이스의 포인터로부터 GetAge()를 호출하려고 하면 컴파일 에러가 되어 버립니다.
func Foo(human *Mammal) {
    _ = human.GetAge()  // コンパイルエラー
}

GetAge() 를 호출하려면 *Mammal 대신 Mammal을 인수로 가져와야 합니다.
func Foo(human Mammal) {
    _ = human.GetAge()
}

원래 Go 언어의 interface란?



다음의 블로그에 알기 쉽게 Go 의 interface 란 무엇인가를 설명하고 있습니다. 정리하면 interface는 형식 정보와 값 정보를 필드에 가진 구조체입니다. 이러한 형태 정보와 값 정보는 interface 를 받는 변수에 대입되는 것으로, 동적으로 변화하는 것 같습니다.

인터페이스 포인터



변수 human 가 interface 의 Mammal 그 자체를 가리키는 경우, 아래의 그림과 같이 되어, 구조체의 실체로부터는 포인터에 해당하는 것이므로 GetAge() 를 호출할 수가 있습니다.



그러나 human 가 interface 의 Mammal 의 포인터인 경우, 아래의 그림을 보면, 구조체의 실체로부터는 포인터의 포인터에 해당하는 것이 되어 버리고 있으므로 GetAge() 를 호출할 수 없었던 것입니다 .



포인터의 포인터는 1 단계 디레퍼런스 해 주면 최종적인 참조처의 메소드를 호출할 수가 있습니다. 즉, interface 의 포인터는 디레퍼런스 해 주는 것으로 메소드 콜이 가능하게 된다고 하는 것입니다.
func Foo(human *Mammal) {
    _ = (*human).GetAge()
}

좋은 웹페이지 즐겨찾기