-
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