메서드를 선언하려면 리시버를 func 키워드와 함께 함수 이름 사이에 중괄호로 명시해야 한다.
func (r Rabbit) info() int {
return r.width * r.height
}
(r rabbit) 부분이 리시버이다. 리시버 덕분에 info() 메서드가 Rabbit 타입에 속한다는 것을 알 수 있다. 이때 구조체 변수(r)는 해당 메서드에서 매개변수처럼 사용된다.
리시버로는 모든 로컬 타입들이 가능한데, 로컬 타입이란 해당 패키지 안에서 type 키워드로 선언된 타입들을 말한다. 그래서 패키지 내 선언된 구조체, 별칭 타입들이 리시버가 될 수 있다.
모든 로컬 타입이 리시버 타입으로 가능한데, 별칭타입으로 기존 타입들을 변경해서 쓰면 된다.
type myInt int
func (a myInt) add(b int) int {
return int(a) + b
}
이처럼 모든 사용자 정의 타입이 리시버 타입이 될 수 있기 때문에 기본 내장 타입도 별칭 타입으로 변환하여 메서드 선언을 할 수 있다.
왜 메서드를 만드는 것인가? 그저 함수의 다른 표현 이라고 볼 수 있지만, 이 둘은 중요한 차이가 있다. 바로 소속이다. 일반 함수는 소속이 없으나 메서드는 리시버에 속한다. 메서드를 사용해 구조체와 묶을 수 있게 된다. 좋은 프로그래밍이라면 결합도를 낮추고 응집도를 높힌다. 메서드는 데이터와 관련 기능을 묶기 때문에 코드 응집도를 높힌다.
데이터와 기능이 서로 결합되지 않고 이곳 저곳에 흩어져 있다면, 즉 응집도가 낮으면 새로운 기능을 추가 할때 흩어진 모든 부분을 검토하고 고쳐야 한다.
코드 수정 범위가 늘어날 수록 버그와 실수가 발생된다. 그래서 코드 조각들을 관련된 데이터 끼리 한곳에 모아 응집도를 높혀야 한다.