프로그래밍

👨‍💻 [Go] Go 에서 제네릭 프로그래밍 이란 무엇이며, 어떻게 활용할 수 있나요?

밝음의기둥 2025. 1. 3. 15:36
반응형

"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."


👨‍💻 안녕하세요, 윌리 프로젝트의 윌리 입니다.

Go 에서 제네릭 프로그래밍 이란 무엇이며, 어떻게 활용할 수 있는지 간략히 알아보았습니다.


질문 >

Go 에서 제네릭 프로그래밍 이란 무엇이며, 어떻게 활용할 수 있나요?

답변 >

Go에서 제네릭 프로그래밍(Generic Programming)은 함수나 데이터 구조가 특정 타입에 의존하지 않고 다양한 타입을 처리할 수 있도록 설계하는 프로그래밍 기법입니다. 이를 통해 코드 재사용성을 높이고 반복적인 코드를 줄일 수 있습니다.

Go는 1.18 버전에서 제네릭을 지원하기 시작했습니다. 제네릭은 타입 파라미터를 사용하여 타입 안정성을 유지하면서도 다양한 타입을 처리할 수 있도록 합니다.


제네릭의 주요 특징

  1. 타입 파라미터 사용: 타입을 함수나 데이터 구조의 매개변수로 전달합니다.
  2. 컴파일 타임 타입 안정성: 실행 전에 타입 검사를 수행하여 오류를 방지합니다.
  3. 코드 재사용성: 여러 타입에 대해 동일한 로직을 작성할 수 있습니다.

기본 문법

1. 타입 파라미터 정의

타입 파라미터는 대괄호([])를 사용하여 정의하며, 일반적으로 T와 같은 단일 문자 이름을 사용합니다.

func 함수명[T any](param T) T {
    // 제네릭 로직
}

2. 여러 타입 파라미터 정의

func 함수명[T, U any](param1 T, param2 U) {
    // 제네릭 로직
}

3. 제네릭 데이터 구조 정의

type 구조체명[T any] struct {
    Field T
}


제네릭 활용 예제

1. 제네릭 함수

package main

import "fmt"

// 제네릭 함수 정의
func Swap[T any](a, b T) (T, T) {
    return b, a
}

func main() {
    x, y := 10, 20
    fmt.Println("Before:", x, y)
    x, y = Swap(x, y)
    fmt.Println("After:", x, y)

    a, b := "hello", "world"
    fmt.Println("Before:", a, b)
    a, b = Swap(a, b)
    fmt.Println("After:", a, b)
}

실행 결과:

Before: 10 20
After: 20 10
Before: hello world
After: world hello


2. 제네릭 데이터 구조

package main

import "fmt"

// 제네릭 구조체 정의
type Stack[T any] struct {
    items []T
}

// Push 메서드
func (s *Stack[T]) Push(item T) {
    s.items = append(s.items, item)
}

// Pop 메서드
func (s *Stack[T]) Pop() T {
    item := s.items[len(s.items)-1]
    s.items = s.items[:len(s.items)-1]
    return item
}

func main() {
    intStack := Stack[int]{}
    intStack.Push(10)
    intStack.Push(20)
    fmt.Println(intStack.Pop()) // 20
    fmt.Println(intStack.Pop()) // 10

    stringStack := Stack[string]{}
    stringStack.Push("Go")
    stringStack.Push("Generics")
    fmt.Println(stringStack.Pop()) // Generics
    fmt.Println(stringStack.Pop()) // Go
}

실행 결과:

20
10
Generics
Go


3. 제네릭 타입 제한과 함께 사용

package main

import (
    "constraints"
    "fmt"
)

// 숫자 타입 제한
func Sum[T constraints.Ordered](a, b T) T {
    return a + b
}

func main() {
    fmt.Println(Sum(10, 20))      // 정수
    fmt.Println(Sum(1.5, 2.3))   // 실수
}

실행 결과:

30
3.8


any 키워드

any는 빈 인터페이스(interface{})의 별칭으로, 모든 타입을 허용합니다. 제네릭에서 타입 제한이 필요 없을 때 사용합니다.

func Print[T any](value T) {
    fmt.Println(value)
}


타입 제한(Type Constraints)

제네릭 함수나 타입에 특정 타입 집합만 허용하도록 제한할 수 있습니다. Go는 constraints 패키지를 통해 기본적인 타입 제한을 제공합니다.

  • constraints.Ordered: 정렬 가능한 타입 (예: int, float, string)
  • 사용자 정의 타입 제한: 인터페이스를 사용하여 커스텀 타입 제한을 정의할 수 있습니다.
type Number interface {
    int | float64
}

func Multiply[T Number](a, b T) T {
    return a * b
}


실용적인 활용 예제

1. 최소값 및 최대값 찾기

package main

import (
    "constraints"
    "fmt"
)

func Min[T constraints.Ordered](a, b T) T {
    if a < b {
        return a
    }
    return b
}

func Max[T constraints.Ordered](a, b T) T {
    if a > b {
        return a
    }
    return b
}

func main() {
    fmt.Println(Min(3, 5))       // 3
    fmt.Println(Max(3.2, 2.8))  // 3.2
    fmt.Println(Min("apple", "banana")) // apple
}

실행 결과:

3
3.2
apple


2. 제네릭 맵 변환 함수

package main

import "fmt"

func Map[T any, U any](input []T, f func(T) U) []U {
    result := make([]U, len(input))
    for i, v := range input {
        result[i] = f(v)
    }
    return result
}

func main() {
    numbers := []int{1, 2, 3, 4}
    squared := Map(numbers, func(x int) int {
        return x * x
    })
    fmt.Println(squared) // [1 4 9 16]
}


제네릭의 장점

  1. 코드 재사용: 여러 타입에 대해 동일한 로직을 중복 작성할 필요가 없습니다.
  2. 타입 안정성: 런타임에 타입 관련 오류가 발생하지 않고, 컴파일 타임에 잡아냅니다.
  3. 가독성 향상: 중복 코드를 제거하여 더 깔끔한 코드를 작성할 수 있습니다.

주의 사항

  1. 복잡성 관리: 제네릭을 과도하게 사용하면 코드가 복잡해질 수 있습니다.
  2. 성능: Go의 제네릭은 컴파일 시 타입을 구체화하므로 런타임 성능에는 큰 영향을 미치지 않지만, 코드 크기가 증가할 수 있습니다.
  3. 타입 제한 사용: 필요하지 않은 경우에는 과도한 타입 제한을 피하는 것이 좋습니다.

Go의 제네릭 프로그래밍은 유연성안전성을 동시에 제공하며, 다양한 데이터 타입을 다루는 함수를 작성할 때 매우 유용합니다. 적절히 활용하면 코드를 효율적이고 간결하게 작성할 수 있습니다.



🎬 유튜브 채널 🎬

 

위로그@WiLog

📢 안녕하세요, 위로그@WiLog 시청자 여러분, 저는 윌리(Willee) 입니다. 📢 위로그@WiLog 는 자기계발을 목적으로 하는 채널 입니다. 📢 오늘도 즐겁게~ 자신을 위한 계발을 함께 해보아요~ d^_^b 📌

www.youtube.com

🎬 치지직 채널 🎬

 

위로그 채널 - CHZZK

지금, 스트리밍이 시작됩니다. 치지직-

chzzk.naver.com


반응형