🔥 메서드와 포인터 Indirection - 2
235자
3분
Go 언어에서는 메서드가 포인터 리시버를 가질 때 값이나 포인터 모두 리시버로 받을 수 있답니다. 반대로, 함수가 값 인자를 받을 때는 해당 타입의 값만 전달할 수 있죠.
예를 들어, 다음과 같이 Vertex 타입의 값 v가 있다고 해볼까요?
go
var v Vertex
fmt.Println(AbsFunc(v)) // OK
fmt.Println(AbsFunc(&v)) // 컴파일 에러!
go
var v Vertex
fmt.Println(AbsFunc(v)) // OK
fmt.Println(AbsFunc(&v)) // 컴파일 에러!
AbsFunc 함수는 Vertex 타입의 값을 인자로 받기 때문에, v를 직접 전달하는 것은 가능하지만 &v와 같이 포인터를 전달하면 컴파일 에러가 발생합니다.
반면에, 값 리시버를 가진 메서드는 호출 시 값이나 포인터 모두 리시버로 사용할 수 있답니다.
go
var v Vertex
fmt.Println(v.Abs()) // OK
p := &v
fmt.Println(p.Abs()) // OK
go
var v Vertex
fmt.Println(v.Abs()) // OK
p := &v
fmt.Println(p.Abs()) // OK
이 경우, p.Abs() 메서드 호출은 (*p).Abs()로 해석됩니다.
go
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
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 언어에서는 메서드와 함수 사이에 미묘한 차이가 있죠. 메서드는 포인터 리시버를 가질 때 값이나 포인터 모두 받을 수 있지만, 함수는 값 인자를 받을 때 해당 타입의 값만 받을 수 있답니다. 이런 차이점을 잘 이해하고 활용하면 더 유연하고 가독성 높은 코드를 작성할 수 있을 거예요!












