Go/Golang - Method
Method 기본
Go에서의 함수(Function)
와 메소드(Method)
- 엄밀히 말하면, Go에서
method
는 함수의 일종이다. 보통 흔히들 생각하는 프로그래밍 언어에서의function
는 파라미터를 받아 로직을 처리한 뒤 리턴하는 역할을 담당하지만, Go에서method
는구조체 밖의 method
를 정의할 때 사용한다. 그리고 어느 구조체의 method 인지를 나타내기 위해receiver
를 사용한다.
Method를 사용하는 (어쩌면 뻔한)이유
method
를 사용해서응집도(cohesion)
를 높인다.- 코드 재사용성 및 가독성을 개선한다.
함수(Function)
와 메소드(Method)
의 비교
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// 구조체 정의
// 구조체 뿐 아니라 type myIntType int 와 같이 사용자 정의 타입도 리시버타입이 될 수 있다.
type account struct {
balance int
}
// Function
func withDrawUsingFunc(a *account, amount int){
a.balance -= amount
}
// Method, Receiver Type은 *account 이다.
func (a *account) withDrawUsingMethod(amount int){
a.balance -= amount
}
func main(){
a := &account{1000}
withDrawUsingFunc(a, 100) // 900
fmt.Println(a.balance)
a.withDrawUsingMethod(200) // 700
fmt.Println(a.balance)
}
- 결국 함수 형태로 선언된
withDrawFunc()
과 메소드 형태로 선언된withDrawMethod()
는 같은 기능을 수행하게 된다. 하지만account
구조체에 엮인withDrawMethod()
를 통해 좀더 객체지향적인 느낌으로 사용이 가능하다.
Method 활용
Value Receiver vs Pointer Receiver
Value Receiver
와Pointer Receiver
는 분명 다른 방향으로 쓰인다.Value Receiver
의 경우 객체의 모든 내용이 복사되기 때문에 복사된 객체는 새로운 주소를 가지게 되는 반면,Pointer Receiver
의 경우 주소를 받는 형식이기 때문에 해당 주소가 가르키는 공간을 공유하게 된다.
그래서 Receiver란?
- 리시버는 메서드를 호출하는
주체
이다. 메서드는 리시버를 통해서만 호출 할 수 있으며 메서드는 리시버에 속한 기능을 표현한다. 모든 로컬 타입은 리시버가 될 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
type account struct{
balance int
firstName string
lastName string
}
// Pointer Method, *account type
func (a1 *account) withDrawPointer(amount int){
a1.balance -= amount
}
// Value Type Method account type
// a2로 account 변수의 모든 값이 복사되기 때문에 a2는 전혀 다른 새로운 인스턴스를 의미하게 된다.
func (a2 account) withDrawValue(amount int) {
a2.balance -= amount
}
// Return Value Type Method account type
func (a3 account) withDrawReturnValue(amount int) account{
a3.balance -= amount
return a3
}
func main(){
var mainA *account = &account{ 100, "Joe", "Park" }
mainA.withDrawPointer(30)
fmt.Println(mainA.balance) // 70
mainA.withDrawValue(20)
fmt.Println(mainA.balance) // 70
var mainB account = mainA.withDrawReturnValue(20)
fmt.Println(mainB.balance) // 50
mainB.withDrawPointer(30)
fmt.Println(mainB.balance) // 20
}
Questions
Q1. Receiver 란 무엇인지 설명하라.
1
리시버는 메서드를 호출하는 `주체` 이다. 메서드는 리시버를 통해서만 호출 할 수 있으며 메서드는 리시버에 속한 기능을 표현한다.
Q2. Value type Method와 Pointer type Method의 차이를 설명하라.
또한 Value type Method를 사용하여 데이터를 조작(예를 들어 현금 인출 기능)할 경우, 몇번의 복사가 일어나는가?
1
2
Pointer type Method는 포인터 변수가 갖는 값 즉 메모리 주소가 복사되지만, Value type Method는 값 전체가 전부 복사된다.
2번 (매서드 호출 시와 메서드 결팟값 반환 시 두 번 복사)