ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Go interface 구현 시 pointer receiver 오류
    공부/GO 2023. 7. 11. 05:46

    https://go-tour-ko.appspot.com/methods/25

     

    Go를 향한 여행

     

    go-tour-ko.appspot.com

    Tour of Go 중 interface에 대한 실습(Method와 Interface #25)을 진행하면서 발생했던 오류에 대해서 다룬다. image.Image interface의 구현을 다루는 다음 코드는 오류를 일으킨다.

    package main
    
    import "image/color"
    import "image"
    import "golang.org/x/tour/pic"
    
    type Image struct{
    	ImageBounds image.Rectangle
    	Color color.Color
    }
    
    func (image *Image) ColorModel() color.Model {
    	return color.RGBAModel
    }
    
    func (image *Image) Bounds() image.Rectangle {
    	return image.ImageBounds
    }
    
    func (image *Image) At(x, y int) color.Color {
    	return image.Color
    }
    	
    func main() {
    	m := Image{
    		image.Rectangle{image.Point{-100, 25}, image.Point{100, 50}}, 
    		color.CMYK{122, 84, 32, 0},
    	}
    	pic.ShowImage(m)
    }

    다음은 image.Image에 대한 인터페이스 정의이다.

    type Image interface {
    	// ColorModel returns the Image's color model.
    	ColorModel() color.Model
    	// Bounds returns the domain for which At can return non-zero color.
    	// The bounds do not necessarily contain the point (0, 0).
    	Bounds() Rectangle
    	// At returns the color of the pixel at (x, y).
    	// At(Bounds().Min.X, Bounds().Min.Y) returns the upper-left pixel of the grid.
    	// At(Bounds().Max.X-1, Bounds().Max.Y-1) returns the lower-right one.
    	At(x, y int) color.Color
    }

    겉보기에는 문제가 없어보인다. Image는 직사각형 정보와 단일색을 담고 있는 구조체로 선언되었고, Image는 다음의 인터페이스 정의에 따라 각자의 메서드를 구현하였다. 예를 들어 main() 안의 변수 m 에 대해 m.ColorModel()을 호출하면 color.RGBAModel이 반환된다. 나머지 메서드들도 마찬가지이다. 그러나 결과는 다음과 같다.

    go: finding module for package golang.org/x/tour/pic
    go: downloading golang.org/x/tour v0.1.0
    go: found golang.org/x/tour/pic in golang.org/x/tour v0.1.0
    # play
    ./prog.go:29:16: cannot use m (variable of type Image) as image.Image value in argument to pic.ShowImage: Image does not implement image.Image (method At has pointer receiver)

    요약하자면 'Image does not implement image.Image', 즉 Image 구조체가(내가 정의한) 이미지 인터페이스를 올바르게 구현하지 않았으며, At라는 메서드가 pointer receiver를 가지고 있으므로 구현에 실패했다는 것이다. 하지만 분명히 m.At(0, 0)과 같은 호출은 잘 동작할 것이다. 이는 pointer receiver가 값 형식도 받기 때문이다. 그러나 내 생각과는 다르다는 것을 알 수 있다.

    이에 대한 대답을 스택오버플로우에서 찾을 수 있었다.

    https://stackoverflow.com/questions/33936081/golang-method-with-pointer-receiver

     

    Golang method with pointer receiver

    I have this example code package main import ( "fmt" ) type IFace interface { SetSomeField(newValue string) GetSomeField() string } type Implementation struct { someField string...

    stackoverflow.com

    두 번째 대답이 나한테는 더 도움이 됐는데, 요는 이렇다. Type이 가진 메서드를 조사할 때, Type의 포인터 메서드(*T를 받는)는 포함되지 않는다는 것이다. 즉, T라는 타입이 있다고 하면, 타입으로서의 메서드 소유는 T와 *T가 다르다는 것이다. 따라서 pointer method로 정의된 메서드는 *T의 메서드에 해당하는 것이다. 따라서 위의 코드에서도 함수를 호출하는 부분(main)에서 인자 m을 포인터인 &m으로 변경해주어야 한다.

    따라서 코드를 다음과 같이 수정한다.

    func main() {
    	m := Image{
    		image.Rectangle{image.Point{-100, 25}, image.Point{100, 50}}, 
    		color.CMYK{122, 84, 32, 0},
    	}
    	pic.ShowImage(&m) // m -> &m
    }

    결과는 다음과 같다. 코드가 잘 실행되는 것을 볼 수 있다.

    요약

    1. go의 interface는 메서드 호출 가능 여부가 아니라 타입이 가진 메서드로 판단한다.

    2. T와 *T가 가진 메서드는 다르다.

    3. 호출할 때 유의해서 호출해주도록 하자.

    '공부 > GO' 카테고리의 다른 글

    Go 언어의 세미콜론 ;  (0) 2023.07.04
    Go tutorial - Hello World!  (0) 2023.07.04
    Vim 설치하기 (Windows)  (0) 2023.07.04
Designed by Tistory.