🔥 메서드와 포인터 Indirection - 2

235자
3분

Go 언어에서는 메서드가 포인터 리시버를 가질 때 값이나 포인터 모두 리시버로 받을 수 있답니다. 반대로, 함수가 값 인자를 받을 때는 해당 타입의 값만 전달할 수 있죠.

예를 들어, 다음과 같이 Vertex 타입의 값 v가 있다고 해볼까요?

var v Vertex
fmt.Println(AbsFunc(v))  // OK
fmt.Println(AbsFunc(&v)) // 컴파일 에러!
 
go

AbsFunc 함수는 Vertex 타입의 값을 인자로 받기 때문에, v를 직접 전달하는 것은 가능하지만 &v와 같이 포인터를 전달하면 컴파일 에러가 발생합니다.

반면에, 값 리시버를 가진 메서드는 호출 시 값이나 포인터 모두 리시버로 사용할 수 있답니다.

var v Vertex
fmt.Println(v.Abs()) // OK
p := &v
fmt.Println(p.Abs()) // OK
 
go

이 경우, p.Abs() 메서드 호출은 (*p).Abs()로 해석됩니다.

package main
 
import (
	"fmt"
	"math"
)
 
type Vertex struct {
	X, Y float64
}
 
func (v Vertex) Abs() float64 {
	// 값 리시버를 가진 Abs 메서드
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
 
func AbsFunc(v Vertex) float64 {
	// Vertex 타입의 값을 인자로 받는 AbsFunc 함수
	return math.Sqrt(v.X*v.X + v.Y*v.Y)
}
 
func main() {
	v := Vertex{3, 4}
	fmt.Println(v.Abs())      // 값으로 메서드 호출
	fmt.Println(AbsFunc(v))   // 값을 함수에 전달
 
	p := &Vertex{4, 3}
	fmt.Println(p.Abs())      // 포인터로 메서드 호출
	fmt.Println(AbsFunc(*p))  // 포인터를 역참조하여 함수에 전달
}
 
go

이렇게 Go 언어에서는 메서드와 함수 사이에 미묘한 차이가 있죠. 메서드는 포인터 리시버를 가질 때 값이나 포인터 모두 받을 수 있지만, 함수는 값 인자를 받을 때 해당 타입의 값만 받을 수 있답니다. 이런 차이점을 잘 이해하고 활용하면 더 유연하고 가독성 높은 코드를 작성할 수 있을 거예요!