[Go] Method Sets

undefcat·2020년 4월 1일
0
post-thumbnail

Method Sets

아래와 같은 Funcer 타입의 인터페이스가 있다고 하자.

type Funcer interface {
  Func()
}

Funcer를 매개변수로 받는 함수가 있다고 하자.

func funcer(f Funcer) {}

마지막으로 T타입을 정의하자.

type T struct{}

이제 이 T타입이 Funcer를 충족하도록 메서드를 구현하자. 이 때, 이 메서드의 receiver 타입과 메서드를 호출하는 변수의 타입(Value or Pointer)에 따라 인터페이스의 충족 기준이 달라진다.

Value

func (t T) Funcer() {}

val := T{} // Value
funcer(val) // valid

ptr := &T{} // Pointer
funcer(ptr) // valid

Pointer

func (t *T) Funcer() {}

val := T{} // Value
funcer(val) // invalid!!!!!!!

ptr := &T{} // Pointer
funcer(ptr) // valid

정리하자면 이렇다.

  1. 변수의 타입이 Value인 경우, 인터페이스의 Method Sets을 충족하려면 인터페이스가 정의하는 모든 메서드의 receiver 타입은 오직 Value여야 한다.
  2. 변수의 타입이 Pointer인 경우, receiver 타입은 ValuePointer든 상관 없다.

왜냐하면 전자의 경우 예상치 못한 결과를 야기할 수 있기 때문에 문법적으로 막아놓은 것이다.

Go 공식문서에서 설명하고 있는 예제는 아래와 같다.

var buf bytes.Buffer
io.Copy(buf, os.Stdin)

receiver의 타입이 Pointer라면, 이는 이 메서드를 호출함으로써 receiver의 값이 변경될 여지가 있다는 뜻이다.

bytes.BufferWrite메서드를 Pointer receiver로 구현하고 있는데, 당연하지만 bytes.Buffer의 값 자체를 변경해야하기 때문이다.

io.Copy는 두번째 매개변수의 값을 첫번째 매개변수로 복사하는 유틸함수다. 첫번째 매개변수는 io.Writer타입의 인터페이스를 받는다.

만약 Value타입의 변수가 Poitner receiver로 정의된 메서드를 구현하고 있다고 여기게 되면 어떻게 될까? 즉, 이 경우 bytes.BufferWrite메서드를 &buf가 아닌 buf가 만족한다고 여겨지면 어떤 문제가 발생할까?(위에서도 언급했듯 bytes.BufferWrite메서드는 Pointer receiver로 정의되어 있다.)

Go에서 모든 것은 Pass By Value로 작동하므로, 매개변수로 Value를 넘기면 복사본이 넘겨진다. 이 복사본에 os.Stdin의 값을 복사해봐야 아무런 의미가 없다! 어차피 io.Copy가 종료되면 사라지기 때문이다! 이는 사용자가 절대로 기대하지 않는 동작이다.

따라서 인터페이스는 Pointer receiver로 정의된 메서드에 대해서는 엄격하게 Pointer타입의 변수만이 이 Method Sets을 구현한다고 본다.

(본 글은 2019-12-08에 작성한 글의 본문 내용을 옮긴 글입니다.)

profile
초보개발자니뮤ㅠ

0개의 댓글