GO 언어의 type method 작성법 (instance receiver와 pointer receiver의 차이)
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 )
결론
- 인스턴스 리시버와 포인터 리시버 모두 '.'(도트)로 접근 가능한가?
- 리시버 타입에 상관 없이 '.'(도트)로 접근한다.
- 인스턴스 리시버를 사용하면 메소드 호출 때마다 객체가 복사/생성되는가?
- 인스턴스 리시버를 쓰면 메소드를 호출할 때마다 리시버 인스턴스가 복사/생성된다.
- 포인터 리시버를 쓰면 리시버 인스턴스가 복사/생성되지 않는다 (있던 것을 그대로 재사용한다).