Generic(제네릭)이란?
Go 1.18부터 도입된 제네릭(Generic) 기능은 하나의 함수나 타입이 다양한 타입을 처리할 수 있도록 해주는 기능입니다.
쉽게 말해, 함수나 구조체를 만들 때 타입을 고정하지 않고 나중에 사용할 때 타입을 지정할 수 있도록 하는 기능입니다.
이전까지는 interface{}를 활용한 방법이 있었지만, 타입 안정성(type safety)이 부족하고 형변환(casting)이 필요했습니다.
제네릭은 이러한 문제를 해결하고, 재사용 가능한 코드를 작성하는 데 큰 도움이 됩니다.
Generic이 필요한 이유
Go에서 Generic이 없던 시절에서는 다음과 같은 일이 자주 발생하였습니다.
func PrintInts(list []int) {
for _, v := range list {
fmt.Println(v)
}
}
func PrintStrings(list []string) {
for _, v := range list {
fmt.Println(v)
}
}
Generic이 없던 시절에는 interface{}를 이용하여 형변환을 이용하거나 아니면 위와 같이 PrintInts, PrintStrings 각각 타입에 맞는 함수를 정의하여 사용해야만 했습니다.
Generic 사용
Generic을 이용하면 타입에 대한 안정성을 유지하며 위와 같이 각 타입별로 함수를 정의하지 않고 다음과 같이 간단하게 코드를 구현하여 사용할 수 있습니다.
func PrintSlice[T any](s []T) {
for _, v := range s {
fmt.Println(v)
}
}
Generic constraint
모든 타입이 아닌, 특정 조건을 가진 타입만 허용하고 싶을 때 다음과 같이 Number(숫자)에 관련된 타입만 정의하여 사용할 수 있습니다.
type Number interface {
int | int8 | int16 | int32 | int64 | float32 | float64
}
func SumNumber[T Number](a, b T) T {
return a + b
}
func main() {
result := SumNumber[int](int(1), int(2))
fmt.Println(result) // 3
result2 := SumNumber[int8](int8(2), int8(3))
fmt.Println(result2) // 5
result3 := SumNumber[float32](float32(1.1), float32(2.2))
fmt.Println(result3) // 3.3
}
Generic constraint 상세
~int는 int와 해당 타입의 별칭까지 포함하는 방법입니다. int 타입을 이용하여 새롭게 정의된 타입은 다음과 같이 정의하여 사용할 수 있습니다.
type Number interface {
~int | ~int8 | ~int16 | ~int32 | ~int64 | ~float32 | ~float64
}
func SumNumber[T Number](a, b T) T {
return a + b
}
type TestType int
func main() {
result := SumNumber(TestType(1), TestType(2))
fmt.Println(result) // 3
}
Generic struct
구조체도 타입 매개변수를 받아 유연하게 설계할 수 있습니다.
type Pair[T, U any] struct {
First T
Second U
}
func main() {
p := Pair[int, string]{First: 1, Second: "hello"}
fmt.Println(p)
}
실제 예제
실제 예제를 이용하여 다음과 같이 여러 사용법에 대하여 간단한 예제를 만들었습니다. 아래 예제를 참고하여 Generic 사용에 많은 참고 바랍니다.
실제 예제: 제네릭 Map 함수
func Map[T any, R any](arr []T, f func(T) R) []R {
result := make([]R, len(arr))
for i, v := range arr {
result[i] = f(v)
}
return result
}
func main() {
squared := Map([]int{1, 2, 3}, func(x int) int {
return x * x
})
fmt.Println(squared) // [1 4 9]
}
실제 예제: Generic을 이용한 Interface 정의
type Comparable[T any] interface {
Less(b T) bool
}
type Person struct {
Name string
Age int
}
func (p Person) Less(other Person) bool {
return p.Age < other.Age
}
func Min[T Comparable[T]](a, b T) T {
if a.Less(b) {
return a
}
return b
}
func main() {
p1 := Person{"Alice", 25}
p2 := Person{"Bob", 30}
fmt.Println(Min(p1, p2)) // Alice
}
'Go언어' 카테고리의 다른 글
Go언어의 benchmark와 test (0) | 2025.03.19 |
---|---|
[addlicense] golang 프로젝트에 라이센스 추가하기 (0) | 2024.04.29 |
golang version upgrade (ubuntu) (0) | 2023.07.09 |
go work 사용해보기 (0) | 2023.07.06 |
Ubuntu(Linux)에서 Go 재설치 (0) | 2022.10.30 |