🔥 타입 확장하기

381자
5분

Go 언어에서는 struct 타입뿐만 아니라 다른 타입에도 메서드를 선언할 수 있습니다. 아래 예제를 살펴보면 MyFloat이라는 숫자 타입에 Abs 메서드를 선언한 것을 볼 수 있죠.

type MyFloat float64
 
func (f MyFloat) Abs() float64 {
	if f < 0 {
		return float64(-f)
	}
	return float64(f)
}
 
go
  • MyFloatfloat64 타입을 기반으로 정의된 사용자 정의 타입입니다.
  • Abs 메서드는 MyFloat 타입의 리시버 f를 가집니다.
  • 메서드 내부에서는 f의 값이 음수인 경우 f를 반환하고, 그 외의 경우에는 f를 그대로 반환합니다.
  • 반환 타입은 float64로 지정되어 있네요.

이렇게 정의된 MyFloat 타입과 Abs 메서드는 아래와 같이 사용할 수 있습니다.

func main() {
	f := MyFloat(-math.Sqrt2)
	fmt.Println(f.Abs())
}
 
go
  • fMyFloat 타입의 변수로, math.Sqrt2로 초기화되었습니다.
  • f.Abs()를 호출하면 Abs 메서드가 실행되어 f의 절댓값을 반환하겠죠.
  • 반환된 값은 fmt.Println을 통해 출력됩니다.

한 가지 주의할 점은, 메서드의 리시버 타입은 반드시 메서드와 같은 패키지 내에서 정의되어야 한다는 것입니다. 즉, 다른 패키지에서 정의된 타입이나 내장 타입(int 등)을 리시버로 사용할 수는 없어요.

그렇다면 서드파티 라이브러리 타입에 메서드를 추가하여 확장하고 싶을 때는 어떻게 해야 할까요? 이런 경우에는 typealias를 사용하면 됩니다.

예를 들어, time 패키지의 Time 타입에 Format 메서드를 추가하고 싶다고 해 보겠습니다.

package main
 
import (
	"fmt"
	"time"
)
 
type MyTime time.Time
 
func (t MyTime) Format(layout string) string {
	return time.Time(t).Format(layout)
}
 
func main() {
	t := MyTime(time.Now())
	formatted := t.Format("2006-01-02 15:04:05")
	fmt.Println(formatted)
}
 
go
  • MyTimetime.Time을 기반으로 정의된 typealias입니다.
  • Format 메서드는 MyTime 타입의 리시버 t를 가지며, layout 문자열을 인자로 받아 포맷팅된 시간 문자열을 반환합니다.
  • 메서드 내부에서는 ttime.Time 타입으로 변환한 후, 기존의 Format 메서드를 호출하여 결과를 반환하고 있네요.

이렇게 typealias를 사용하면 마치 time.Time 타입 자체에 Format 메서드를 추가한 것처럼 사용할 수 있습니다.

t := MyTime(time.Now())
formatted := t.Format("2006-01-02 15:04:05")
 
go
  • tMyTime 타입의 변수로, time.Now()를 통해 현재 시간으로 초기화되었어요.
  • t.Format("2006-01-02 15:04:05")를 호출하면 MyTime에 정의된 Format 메서드가 실행되겠죠.

이처럼 Go 언어에서는 struct 외에도 다양한 타입에 메서드를 추가할 수 있어서 코드의 가독성과 재사용성을 높일 수 있답니다. 또한 typealias를 활용하면 외부 패키지의 타입을 마치 자신의 타입인 것처럼 다룰 수 있어서 코드의 표현력도 좋아지죠.

메서드와 typealias를 잘 활용하면 코드를 더욱 간결하고 명확하게 작성할 수 있으니 적극적으로 활용해 보시는 것은 어떨까요?

lecture image

위 다이어그램은 Go 언어에서 메서드와 typealias의 관계를 나타낸 것이랍니다. 메서드를 정의할 때는 리시버 타입이 반드시 같은 패키지 내에서 정의되어야 해요. 하지만 typealias를 사용하면 외부 패키지의 타입도 마치 자신의 타입인 것처럼 확장할 수 있죠.