Go Generics(제네릭)❓

beluga000·2024년 8월 2일
0
post-thumbnail

제네릭 - Generics

제네릭(Generics)은 프로그래밍에서 데이터 타입을 일반화하는 방법으로, 코드의 재사용성과 타입 안정성을 높이기 위해 사용됩니다. 제네릭을 통해 동일한 코드 구조를 여러 데이터 타입에 대해 작성할 수 있으며, 컴파일 타임에 타입 검사를 통해 오류를 방지할 수 있습니다.

주요 개념

1. 타입 매개변수(Type Parameters)

  • 함수나 타입 정의에서 사용되는 일반화된 타입을 나타냅니다.
  • 타입 매개변수는 대괄호 []안에 정의됩니다.
  • 예를 들어 func Print[T any](value T)에서 T는 타입 매개변수입니다.

2. 타입 제약조건(Type Constraints)

  • 타입 매개변수에 적용할 수 있는 제약 조건을 정의합니다.
  • 특정 인터페이스나 타입 집합을 지정하여 타입 매개변수가 해당 조건을 만족하도록 할 수 있습니다.
  • 예를 들어 type Number interface { int | float64 }는 Number 인터페이스를 구현하는 타입만 허용합니다.

제네릭의 이점

1. 코드 재사용성

  • 제네릭을 사용하면 동일한 코드를 여러 데이터 타입에 대해 재사용할 수 있습니다.
  • 중복도니 코드를 줄이고 유지보수를 용이하게 합니다.

2. 타입 안전성

  • 컴파일 타임에 타입 검사를 수행하여 타입 불일치로 인한 오류를 방지합니다.
  • 잘못된 타입 사용을 방지하고 코드의 안정성을 높입니다.

Go의 Generics

Go언어에서 제네릭은 1.18 버전부터 도입되었습니다.

제네릭 함수 정의는 아래와 같습니다.

package main

import "fmt"

// 제네릭 함수
func Print[T any](value T) {
    fmt.Println(value)
}

func main() {
    Print(42)        // int 타입 인수
    Print("Hello")   // string 타입 인수
    Print(3.14)      // float64 타입 인수
}

제네릭 타입의 정의는 아래와 같습니다.

package main

import "fmt"

// 제네릭 타입 정의
type Pair[T any, U any] struct {
    First  T
    Second U
}

func main() {
    p1 := Pair[int, string]{First: 1, Second: "one"}
    p2 := Pair[string, float64]{First: "pi", Second: 3.14}

    fmt.Println(p1)
    fmt.Println(p2)
}

제네릭 인터페이스를 정의하여 특정 타입 제약 조건을 지정할 수 있습니다.

package main

import "fmt"

// 제네릭 인터페이스
type Adder[T any] interface {
    Add(a, b T) T
}

// int 타입에 대한 Adder 인터페이스 구현
type IntAdder struct{}

func (IntAdder) Add(a, b int) int {
    return a + b
}

// float64 타입에 대한 Adder 인터페이스 구현
type FloatAdder struct{}

func (FloatAdder) Add(a, b float64) float64 {
    return a + b
}

func main() {
    var intAdder Adder[int] = IntAdder{}
    var floatAdder Adder[float64] = FloatAdder{}

    fmt.Println(intAdder.Add(1, 2))        // 3
    fmt.Println(floatAdder.Add(1.1, 2.2))  // 3.3
}

제네릭 타입 제약 조건을 추가하여 특정 인터페이스를 구현하는 타입만 허용할 수 있습니다.

package main

import "fmt"

// 제네릭 타입 제약 조건으로 Number 인터페이스 정의
type Number interface {
    int | int64 | float64
}

// 제네릭 함수에 타입 제약 조건 추가
func Sum[T Number](a, b T) T {
    return a + b
}

func main() {
    fmt.Println(Sum(1, 2))          // 3 (int)
    fmt.Println(Sum(int64(1), 2))   // 3 (int64)
    fmt.Println(Sum(1.1, 2.2))      // 3.3 (float64)
}

아래 코드는 제네릭 타입, 함수, 그리고 제약 조건을 모두 사용하여 다양한 타입의 값을 처리하고, 제네릭의 강력함과 유연성을 보여주는 예시 입니다.

package main

import "fmt"

// 제네릭 타입 제약 조건으로 Number 인터페이스 정의
type Number interface {
    int | int64 | float64
}

// 제네릭 함수에 타입 제약 조건 추가
func Sum[T Number](a, b T) T {
    return a + b
}

func main() {
    fmt.Println(Sum(1, 2))          // 3 (int)
    fmt.Println(Sum(int64(1), 2))   // 3 (int64)
    fmt.Println(Sum(1.1, 2.2))      // 3.3 (float64)
}
profile
Developer

0개의 댓글