- 출처: https://go.dev/doc/effective_go#methods
- Methods
메소드는 포인터나 인터페이스를 제외하고 명명된 유형에 대해 정의될 수 있다. 즉 Receiver가 반드시 구조체가 아니어도 된다.
예를 들어 Append라는 함수를 slice의 메소드로 정의할 수 있는데, 이렇게 하기 위해서는 우선 메소드를 묶을 수 있도록 명명된 유형을 정의해야 한다. 그리고 Receiver로 해당 형을 기술해준다.
type ByteSlice []byte
func (slice ByteSlice) Append(data []byte) []byte {
// Body exactly the same as the Append function defined above.
}
위의 메소드는 갱신된 slice를 반환한다. 아래 코드와 같이 receiver를 ByteSlice에 대한 pointer로 변경하여 method를 정의하면 slice를 반환하지 않아도 된다.
func (p *ByteSlice) Append(data []byte) {
slice := *p
// Body as above, without the return.
*p = slice
}
위의 코드를 보면 갱신된 slice를 반환하지 않았다. 대신 메소드에서 호출자의 slice를 덮어썼다. 이를 더 정성스럽게 변경하면 우리가 익숙한 io.Writer 인터페이스 형태로 변경할 수 있다.
func (p *ByteSlice) Write(data []byte) (n int, err error) {
slice := *p
// Again as above.
*p = slice
return len(data), nil
}
이제 *ByteSlice 형이 표준 인터페이스인 io.Writer를 만족하게 되었으므로 아래와 같이 Fprintf 함수에도 해당 형을 자연스럽게 사용할 수 있게 된다.
var b ByteSlice
fmt.Fprintf(&b, "This hour has %d days\n", 7)
위의 코드에서 ByteSlice 의 주소를 넘겼는데 *ByteSlice만이 io.Writer 인터페이스를 만족하기 때문이다. receiver에 대한 pointer와 value의 규칙은 value 메소드의 경우 pointer와 value 둘 다에서 실행 가능하지만, pointer method의 경우 pointer 에서만 실행이 가능하다.
이런 규칙은 pointer 메소드가 receiver를 수정할 수 있기 때문에 발생한다. value에서 method를 수행하면 value에 대해 호출하면 receiver 역시 value의 복사본이기 때문에 수정사항이 버려진다. 이런 경우 발생할 수 있는 실수를 방지하기 위해 앞에서 언급한 규칙을 강제한다.
다만 한가지 편리함을 위해 예외를 적용해주는데 value에 주소를 지정할 수 있는 경우 golang은 자동으로 주소 연산자(&)을 삽입하여 value에 대한 pointer 메소드를 실행해준다. 예를 들어 변수 b가 주소를 지정할 수 있어서 b.Write 와 같이 Write 메소드를 호출하면 compiler는 자동으로 (&b).Write로 다시 써준다.
'Language > Go' 카테고리의 다른 글
Effective Go - Embedding (0) | 2022.05.29 |
---|---|
Effective Go - Interfaces and other types (0) | 2022.05.26 |
Effective Go - Array and Slice (0) | 2022.05.08 |
Effective Go - New 와 Make (0) | 2022.05.07 |
Effective Go - Functions (0) | 2022.05.07 |
댓글