시작하며

Go 언어에서 method는 함수의 일종이지만, 특정 타입에 귀속된다는 점에서 일반 함수와 구별된다. 구조체에 메소드를 붙이면 코드의 응집도와 재사용성이 높아진다. Value Receiver와 Pointer Receiver의 차이를 명확히 이해하는 것이 핵심이다.
Method 기본
Go에서의 함수(Function)와 메소드(Method)
Go에서 method는 구조체 밖에 정의하되, 어느 타입에 속하는지를 나타내기 위해 receiver를 명시한다. 구조체뿐 아니라 type myIntType int 와 같은 사용자 정의 타입도 리시버 타입이 될 수 있다.
Method를 사용하는 이유
method를 사용해서응집도(cohesion)를 높인다.- 코드 재사용성 및 가독성을 개선한다.
함수(Function)와 메소드(Method) 비교
// 구조체 정의
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)
}결국 withDrawUsingFunc() 과 withDrawUsingMethod()는 같은 기능을 수행한다. 하지만 account 구조체에 엮인 메소드 형태로 좀 더 객체지향적인 느낌으로 사용이 가능하다.
Method 활용
Value Receiver vs Pointer Receiver
Value Receiver: 객체의 모든 내용이 복사되기 때문에 복사된 객체는 새로운 주소를 가지게 된다.Pointer Receiver: 주소를 받는 형식이기 때문에 해당 주소가 가리키는 공간을 공유하게 된다.
그래서 Receiver란?
리시버는 메서드를 호출하는 주체이다. 메서드는 리시버를 통해서만 호출할 수 있으며, 메서드는 리시버에 속한 기능을 표현한다. 모든 로컬 타입은 리시버가 될 수 있다.
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
}정리하며
Go의 메소드는 리시버를 통해 특정 타입에 귀속된 함수다. Pointer Receiver는 원본 객체를 직접 수정할 때, Value Receiver는 복사본에서 동작할 때 사용한다. Value Receiver로 데이터를 조작하면 메소드 호출 시와 반환 시 두 번 복사가 발생하므로 성능에 민감한 경우에는 Pointer Receiver를 사용하는 것이 낫다.
연습 문제
Q1. Receiver란 무엇인지 설명하라.
리시버는 메서드를 호출하는 주체이다. 메서드는 리시버를 통해서만 호출할 수 있으며 메서드는 리시버에 속한 기능을 표현한다.
Q2. Value type Method와 Pointer type Method의 차이 / Value type Method에서 복사가 몇 번 발생하는가?
Pointer type Method는 포인터 변수가 갖는 값(메모리 주소)이 복사되지만, Value type Method는 값 전체가 전부 복사된다.
2번 (메서드 호출 시와 메서드 결괏값 반환 시 두 번 복사)