GO 언어의 type method 작성법 (instance receiver와 pointer receiver의 차이)

in #golang6 years ago

GO 언어의 type method 작성법 (instance receiver와 pointer receiver의 차이)

개요

다음 내용이 궁금했다.

  • 인스턴스 리시버와 포인터 리시버 모두 '.'(도트)로 접근 가능한가?
    • C++에서는 인스턴스의 메소드는 '.' (도트)로 포인터의 메소드는 '->' (화살표)로 접근한다. GO 언어에서도 이런 차이가 있는지 궁금했다.
  • 인스턴스 리시버를 사용하면 메소드 호출 때마다 객체가 복사/생성되는가?
    • 함수 호출할 때 인자가 복사/생성되는 것처럼 리시버도 같은 방식으로 처리되는지 궁금했다.

테스트 코드 && 결과

테스트 코드

  1 //
  2 // test-code to check
  3 //  - can both instance-method and pointer-method are called by '.' ?
  4 //  - what is the 'this' address in both methods (same or diff) ?
  5 //
  6 package main
  7
  8 import "fmt"
  9
 10 type MyTypeA int
 11 type MyTypeB int
 12
 13 func (m MyTypeA) String() string {
 14   s := fmt.Sprintf("MyTypeA( val=%d, addr=%p )", int(m), &m)
 15   return s
 16 }
 17
 18 func (m MyTypeA) say() {
 19   fmt.Println("Hey A World,", m)
 20 }
 21
 22 func (m *MyTypeB) String() string {
 23   s := fmt.Sprintf("MyTypeB( val=%d, addr=%p )", int(*m), m)
 24   return s
 25 }
 26
 27 func (m *MyTypeB) say() {
 28   fmt.Println("Hey B World,", m)
 29 }
 30
 31 func main() {
 32   a := MyTypeA(10)
 33   b := MyTypeB(11)
 34   fmt.Printf("&a=%p, type(a)= %T, val(a)= %v\n", &a, a, a)
 35   fmt.Printf("&b=%p, type(b)= %T, val(b)= %v\n", &b, b, &b)
 36
 37   a.say()
 38   b.say()
 39 }

결과

$ go build test-code.go
$ ./test-code
&a=0xc4200140b0, type(a)= main.MyTypeA, val(a)= MyTypeA( val=10, addr=0xc4200140d8 )
&b=0xc4200140b8, type(b)= main.MyTypeB, val(b)= MyTypeB( val=11, addr=0xc4200140b8 )
Hey A World, MyTypeA( val=10, addr=0xc420014120 )
Hey B World, MyTypeB( val=11, addr=0xc4200140b8 )

결론

  • 인스턴스 리시버와 포인터 리시버 모두 '.'(도트)로 접근 가능한가?
    • 리시버 타입에 상관 없이 '.'(도트)로 접근한다.
  • 인스턴스 리시버를 사용하면 메소드 호출 때마다 객체가 복사/생성되는가?
    • 인스턴스 리시버를 쓰면 메소드를 호출할 때마다 리시버 인스턴스가 복사/생성된다.
    • 포인터 리시버를 쓰면 리시버 인스턴스가 복사/생성되지 않는다 (있던 것을 그대로 재사용한다).