Golang 기초 (14) : 메서드에 대하여

Eon Kim·2022년 5월 22일
0

Golang 기초 

목록 보기
14/14
post-thumbnail

안녕하세요, 주니어 개발자 Eon입니다.

이번에 다룰 내용은 메서드입니다.

📝 Method

메서드는 함수와 큰 차이가 없으나, 객체에 속한다는 특징이 있습니다.
함수는 객체와 상관없이 호출하면 사용이 가능하지만, 메서드는 해당 객체를 통해서만 호출이 가능합니다.

package main

import "fmt"

type Parameter struct {
	XX string
}

func nameOfFunction(p *Parameter) {
	p.XX = "YY"
}

func main() {
	p := Parameter{}
	p.XX = "XX"
	nameOfFunction(&p)
	fmt.Println(p)
}
package main

import "fmt"

type Receiver struct {
	XX string
}

func (r *Receiver) nameOfMethod() {
	r.XX = "YY"
}

func main() {
	r := Receiver{}
	r.XX = "XX"
	r.nameOfMethod()
	fmt.Println(r)
}

📌 왜 Method를 사용할까?

그렇다면 왜 제약조건이 더 붙은 메서드를 사용할까?
유지보수 측면에서 더 유리할 수 있습니다.
프로그램이 동작하는 데에 있어서는 큰 차이가 없으나, 객체의 타입마다 사용할 수 있는 메서드를 제한할 수 있습니다.

  • 어떤 객체에서 에러가 발생
    • 그 객체의 메서드를 디버깅하여 개선할 수 있음
  • 기능을 분리하여 객체지향 모델을 만들 수 있음
    • 기능을 독립적으로 수행하게 하기 위함

📍 Receiver

메서드는 위에 함수와 다르게 함수명과 함수 선언부 사이에 리시버가 들어갑니다.
Receiver는 어떤 타입의 객체가 사용할 수 있는 메서드인지 제한하고, 해당 타입의 객체만 이 메서드를 사용할 수 있게 합니다.

func (s *Student) StudentInfoUpdate() {
// TODO: update student's information
...
}

여기서 StudentInfoUpdate()라는 메서드는 Student라는 타입의 리시버가 지정되어 있습니다.
Student 객체 말고는 이 메서드를 사용할 수 없습니다.



📌 사용법

함수와 마찬가지로 포인터형밸류형이 있습니다.

포인터형은 당연하게도 인스턴스를 직접 조작합니다.
밸류형은 값을 복사해서 사용하기 때문에 포인터형과 다르게 인스턴스를 새로 만들어서 조작합니다.

📍 포인터형 리시버 / 메서드

package main

import "fmt"

type Student struct {
	Name  string
	Age   int8
	Email string
}

func (s *Student) HappyNewYear() {
	s.Age += 1
}

func (s *Student) UpdateEmail(NewEmail string) {
	s.Email = NewEmail
}

func main() {
	s1 := new(Student)
	s1.Name = "David"
	s1.Age = 20
	s1.Email = "empty@email.invalid"
	s1.HappyNewYear()
	s1.UpdateEmail("david@email.com")
	fmt.Println(*s1)
}

/* output
{David 21 david@email.com}
*/

위와 같이 반환값이 없어도 포인터인스턴스를 직접 조작하기 때문에 변경된 값이 유지되는 것을 볼 수 있습니다.


📍 밸류형 리시버 / 메서드 (반환 없이)

package main

import "fmt"

type Student struct {
	Name  string
	Age   int8
	Email string
}

func (s Student) HappyNewYear() {
	s.Age += 1
}

func (s Student) UpdateEmail(NewEmail string) {
	s.Email = NewEmail
}

func main() {
	s2 := Student{}
	s2.Name = "David"
	s2.Age = 20
	s2.Email = "empty@email.invalid"
	s2.HappyNewYear()
	s2.UpdateEmail("david@email.com")
	fmt.Println(s2)
}


/* output
{David 20 empty@email.invalid}
*/

위와 같이 반환하지 않고 객체를 밸류형으로 조작하는 경우, 호출된 메서드에서 새로운 인스턴스 가 만들어집니다.

func (s Student) UpdateEmail(NewEmail string) {
	s.Email = NewEmail
    fmt.Println(s.Email)
}
/* output
david@email.com
*/

이렇게 UpdateEmail() 메서드 내에서는 값이 정상적으로 변경된 것을 확인할 수 있습니다.
값 반환을 하지 않았기 때문에 해당 메서드 내에서 변경된 값은 의도한 s2 객체에 아무런 영향을 주지 않습니다.


📍 밸류형 리시버 / 메서드 (반환 포함)

package main

import "fmt"

type Student struct {
	Name  string
	Age   int8
	Email string
}

func (s Student) HappyNewYear() Student {
	s.Age += 1
	return s
}

func (s Student) UpdateEmail(NewEmail string) string {
	s.Email = NewEmail
	return s.Email
}

func main() {
	s2 := Student{}
	s2.Name = "David"
	s2.Age = 20
	s2.Email = "empty@email.invalid"
	s2 = s2.HappyNewYear()
	s2.Email = s2.UpdateEmail("david@email.com")
	fmt.Println(s2)
}


/* output
{David 21 david@email.com}
*/

위와 같이 알맞게 값을 반환했더니 의도한 대로 AgeEmail이 변경된 것을 확인할 수 있습니다.



이번 포스트는 메서드에 대한 내용이었습니다.

감사합니다.👍

profile
주니어 개발자

1개의 댓글

comment-user-thumbnail
2023년 8월 6일

좋은 글 감사합니다!!

답글 달기