개요
이번 블로그 포스트에서는 Golang의 Method
(메서드)에 대해 자세히 알아보고 사용하는 방법에 대해서 살펴보려고 합니다. 이 블로그 포스트에서 소개하는 코드는 다음 링크를 통해 확인하실 수 있습니다.
메서드
Golang에서 메서드는 함수의 한 종류로써, 타입에 속한 함수를 메서드라고 합니다. 함수는 일반적으로 타입과 독립적으로 존재하지만, 메서드는 타입에 종속되게 됩니다. Golang에서는 어떤 타입도 메서드를 가질 수 있습니다.
Golang에서 메서드는 다음과 같이 정의합니다.
// func 리시버 메서드명
func (r Person) greeting() string {
return r.width * r.height
}
리시버에는 패키지의 모든 지역 타입(패키지 안에 선언된 타입)이 가능하며, 메서드는 리시버에 종속된 함수가 됩니다.
이를 확인하기 위해 main.go
파일을 생성하고 다음과 같이 수정합니다.
package main
import "fmt"
type Person struct {
Name string
Age int
}
func (r Person) greeting() string {
return "Hello, " + r.Name
}
func main() {
p := Person{Name: "Rob", Age: 4}
fmt.Println(p.greeting())
}
이를 실행하면 다음과 같은 결과가 출력됩니다.
# go run main.go
Hello, Rob
객체지향 프로그래밍
Golang은 객체지향 프로그래밍 언어(OOP, Object Oriented Programming language)입니다. 여기서 객체(Object)는 데이터(State)와 기능(Function)을 가지는 것을 의미합니다.
만약, Golang에 메서드가 존재하지 않으면, 데이터(타입)과 기능(함수)이 따로 존재하게 됩니다. 그렇면 Golang에서 객체를 생성할 수 없으며, 객체 지향 프로그래밍을 할 수 없게 됩니다.
Golang에서는 메서드를 통해, 데이터에 종속된 기능들을 구현할 수 있게 되어 객체지향 프로그래밍을 할 수 있게 됩니다. 또한, 메서드는 다음과 같이 데이터간의 관계도 정의할 수 있습니다.
// Student <- Enroll -> Course
func (s * Student) Enroll(c *Course) {
...
}
// Student <- SendReport -> Professor, Report
func (s * Student) SendReport(p *Professor, r *Report) {
...
}
물론, 함수를 사용해도 메서드와 동일한 기능을 구현할 수 있습니다. 기능상으로는 함수와 메서드는 동일합니다. 다만, 함수는 주어진 데이터를 단순히 연산만 하는 반면, 메서드는 데이터에 종속되어 있다는 개념의 차이만 존재합니다.
포인터 타입 메서드와 값 타입 메서드
Golang으로 프로그래밍을 하다보면, 포인터 타입 메서드와 값 타입 메서드가 존재하는 것을 확인할 수 있습니다. Golang에서는 주로 타입의 성격에 따라 포인터 타입 메서드와 값 타입 메서드는 메서드를 구별해서 사용하게 됩니다.
메서드를 사용하였을 때, 새로운 객체를 생성할 필요가 있으면, 값 타입 메서드를 사용하게 되며, 새로운 객체를 생성할 필요가 없을 때 포인터 타입 메서드를 사용하게 됩니다.
type Person struct {
Name string
Age int
}
func (p *Person) AddAge() {
p.Age += 1
}
예를 들어 Person
이라는 타입이 있습니다. Person 타입으로 만든 사람 데이터의 나이가 한 살 증가하더라도, 해당 사람은 동일한 사람이여야 하므로, 포인터 타입 메서드를 사용하게 됩니다.
type Temperature float64
func (t Temperature) Up(temp float64) Temperature {
return t + Temperature(temp)
}
반대로 Temperature
라는 타입은 온도가 올라가면, 이전 온도와 상승된 온도는 개념적으로 다르므로 값 타입 메서드를 사용하는 것이 적합합니다.
이를 확인하기 위해 main.go
파일을 다음과 같이 수정합니다.
package main
import "fmt"
type Person struct {
Name string
Age int
}
func (p *Person) AddAge() {
p.Age += 1
}
type Temperature float64
func (t Temperature) Up(temp float64) Temperature {
return t + Temperature(temp)
}
func main() {
p1 := Person{Name: "Rob", Age: 4}
fmt.Println("P1: ", p1)
p1.AddAge()
fmt.Println("P1: ", p1)
t := Temperature(30.0)
fmt.Println("T: ", t)
t = t.Up(4.0)
fmt.Println("T: ", t)
}
이를 실행하면 다음과 같은 결과를 얻을 수 있습니다.
# go run main.go
P1: {Rob 4}
P1: {Rob 5}
T: 30
T: 34
생성자와 소멸자
Golang에는 생성자와 소멸자가 존재하지 않습니다. 따라서 생성자가 필요한 경우, 패키지에서 생성자처럼 동작하는 함수를 만들어 제공해야 합니다.
이를 확인하기 위해 group/main.go
파일을 만들고 다음과 같이 수정합니다.
package group
type Member struct {
Name string
Age int
}
func NewMember(name string, age int) *Member {
return &Member{Name: name, Age: age}
}
여기서 NewMember
함수가 생성자 역할을 하는 함수에 해당합니다.
그런 다음 다음 명령어를 실행하여, 모듈을 생성합니다.
go mod init github.com/dev-yakuza/study-golang/method/group
go mod tidy
그런 다음, 이를 실제로 사용할 main
패키지를 생성해 봅시다. group
폴더와 동일한 위치에서 main/main.go
파일을 생성하고 다음과 같이 수정합니다.
package main
import (
"fmt"
"github.com/dev-yakuza/study-golang/method/group"
)
func main() {
member1 := group.Member{Name: "John", Age: 20}
member2 := group.NewMember("Paul", 30)
fmt.Println(member1)
fmt.Println(member2)
}
그리고 다음 명령어를 사용하여 모듈을 생성하고, 로컬 모듈을 연결합니다.
go mod init github.com/dev-yakuza/study-golang/method/main
go mod edit -replace github.com/dev-yakuza/study-golang/method/group=../group
go mod tidy
그리고 다음 명령어를 사용하여 생성한 프로그램을 실행해 봅니다.
go run main.go
그럼 다음과 같은 결과를 확인할 수 있습니다.
{John 20}
&{Paul 30}
Golang에서 모듈을 사용하는 방법에 대해서는 아래에 블로그 포스트를 참고하시기 바랍니다.
Embedded field 메서드
Golang의 구조체는 Embedded field
를 가질 수 있습니다. Embedded field
에 관한 자세한 내용은 아래에 블로그 포스트를 참고하시기 바랍니다.
다음과 같이 구조체가 Embedded field
를 가질 수 있으며, Embedded field의 구조체가 다음과 같이 메서드를 가지고 있을 수 있습니다.
type Member struct {
Name string
Age int
}
func (p *Member) AddAge() {
p.Age += 1
}
type Group struct {
Member
Grade int
}
이런 경우, 다음과 같이 Embedded field의 메서드를 사용할 수 있습니다.
g := Group{Member: Member{Name: "John", Age: 20}, Grade: 1}
g.AddAge()
fmt.Println(g)
이를 확인하기 위해 main.go
파일을 다음과 같이 수정합니다.
package main
import "fmt"
type Member struct {
Name string
Age int
}
func (p *Member) AddAge() {
p.Age += 1
}
type Group struct {
Member
Grade int
}
func main() {
g := Group{Member: Member{Name: "John", Age: 20}, Grade: 1}
fmt.Println(g)
g.AddAge()
fmt.Println(g)
}
그리고 이를 실행하면 다음과 같은 결과를 얻을 수 있습니다.
# go run main.go
{{John 20} 1}
{{John 21} 1}
완료
이것으로 Golang에서 메서드를 정의하고 사용하는 방법에 대해서 알아보았습니다. 또한, 메서드의 특징과 생성자를 만드는 방법에 대해서도 알아보았습니다.
제 블로그가 도움이 되셨나요? 하단의 댓글을 달아주시면 저에게 큰 힘이 됩니다!
앱 홍보
Deku
가 개발한 앱을 한번 사용해보세요.Deku
가 개발한 앱은 Flutter로 개발되었습니다.관심있으신 분들은 앱을 다운로드하여 사용해 주시면 정말 감사하겠습니다.