Golang
[Go] The Go Programming Language #6-1: 메소드 선언
leejiwonn
2021. 12. 2. 02:12
이 시리즈는 "The Go Programming Language" 책을 바탕으로 작성되었습니다.
6.1 메소드 선언
Go는 객체지향 프로그래밍 언어이다.
Go에서의 메소드란?
// 예1) 표준 라이브러리의 메소드 사용 : time.Duration의 Seconds 메소드
const day = 24 *time.Hour
fmt.Println(day.Seconds()) // "86400"
// 예2) Celsius 타입의 String 메소드를 직접 정의
func (c Celsius) String() string {
return fmt.Sprintf("%g℃", c)
}
// 예3) 배열 타입의 perim 메소드 직접 정의
perim := Path{
{1, 1}
{5, 4}
}
fmt.Println(perim.Distance())
- Go에서는 객체를 단순히 메소드를 가진 값이나 변수로 정의하며, 메소드는 특정 타입과 관련된 함수로 정의함.
⇒ 타 언어의 클래스가 필드와 메소드를 함께 갖는 것과 달리, Go에서는 struct가 필드만을 가지며 메소드는 별도로 정의함. - 간단히 말하자면, 메소드란 객체에 연결된 특별한 형태의 함수! 우리가 특정 객체를 통해서 하려고 하는 작업들(함수들)이라 생각하면 편함.
- Go는 다른 수많은 객체지향 언어들과는 다르게 숫자, 문자열, 슬라이스, 맵, 함수 등 어떠한 타입에도 메소드를 붙일 수 있음. (포인터, 인터페이스 제외)
메소드 선언법 (Receiver Parameter)
package geometry
type Point struct{ X, Y float64 }
// 전통적인 함수
func Distance(p, q Point) float64 {
return math.Hypot(q.X-p.X, q.Y-p.Y)
}
// 동일한 역할을 수행하는 Point 타입의 메소드
**func (p Point) Distance(q Point) float64 {**
return math.Hypot(q.X-p.X, q.Y-p.Y)
}
// 테스트 결과 :
p := Point{1, 2}
q := Point{4, 6}
fmt.Println(Distance(p, q)) // "5", 함수 호출
**fmt.Println(p.Distance(q))** // "5", 메소드 호출
- 일반 함수 선언을 변형해 함수명 앞에 부가적인 파라미터를 추가한 형태로 선언함. 이때, 파라미터는 함수를 파라미터 타입에 추가함.
- 파라미터 p를 메소드의 Receiver(수신자 : 객체에 메시지를 전송한다)라 부르며, Go에서는 수신자에 this나 self 등의 특별한 이름을 사용하지 않음.
- 메소드를 호출할 때 Receiver의 인수는 메소드명 앞에 씀.
- p.Distance 표현식은 Point 타입의 리시버 p에 대응하는 Distance 메소드를 선택하므로 셀렉터(selector)라고 함.
동일한 메소드명을 가지는 경우
- 특정 타입의 모든 메소드명은 유일해야 하지만, 각 타입에는 자신만의 네임스페이스가 있으므로 서로 다른 타입에서는 같은 메소드명을 사용할 수 있음.
- 이처럼 컴파일러는 메소드명과 수신자의 타입으로 어떤 함수를 호출할지 결정함.
- 위 선언법의 예제에서, 두 Distance 함수 선언 간에는 충돌이 일어나지 않음.
⇒ 첫 번째는 패키지 수준 함수 geometry.Distance를 선언하며, 두 번째는 Point 타입의 메소드를 선언하므로 이름이 Point.Distance가 되기 때문임.
+) 더 알아가기
- 수신자의 이름은 자주 사용되므로 짧으면서 메소드들과 일관된 이름을 고르는 것이 좋음.
⇒ 일반적으로 Point의 p와 같은 타입명의 첫 번째 글자를 사용함. - Value Receiver 를 사용하면 사이드이펙트 발생이 적어짐.