[Go]

[Go] 제네릭 사용 예 (Example of using generics)

dogfootman 2024. 6. 23. 00:58

개요

go 1.18에서 추가 된 제네릭의 사용 예

 

 

 

1. 함수에서의 사용

package main

import "fmt"

func Filter[T any](list []T, predicate func(T) bool) []T {
	var result []T
	for _, v := range list {
		if predicate(v) {
			result = append(result, v)
		}
	}
	return result
}

func main() {
	
	// 짝수만 필터
	nums := []int{1, 2, 3, 4, 5, 6}
	evens := Filter(nums, func(n int) bool {
		return n%2 == 0
	})
	fmt.Println(evens) // [2 4 6]

	// 길이가 5가 넘는 문자열만 필터
	strings := []string{"apple", "banana", "cherry", "date"}
	filteredStrings := Filter(strings, func(s string) bool {
		return len(s) > 5
	})
	fmt.Println(filteredStrings) // ["banana", "cherry"]
}
  • T는 타입 매개변수
  • any

 

 

 

2. 구조체에서의 사용

package main

import "fmt"

type Stack[T any] struct {
	elements []T
}

func (s *Stack[T]) Push(element T) {
	s.elements = append(s.elements, element)
}

func (s *Stack[T]) Pop() T {
	if len(s.elements) == 0 {
		var zero T
		return zero
	}
	element := s.elements[len(s.elements)-1]
	s.elements = s.elements[:len(s.elements)-1]
	return element
}

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

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

 

package main

import "fmt"

type Pair[T any] struct {
	first, second T
}

func (p Pair[T]) Swap() Pair[T] {
	return Pair[T]{p.second, p.first}
}

func main() {
	intPair := Pair[int]{1, 2}
	fmt.Println(intPair.Swap()) // {2 1}

	stringPair := Pair[string]{"hello", "world"}
	fmt.Println(stringPair.Swap()) // {world hello}
}

 

 

 

3. 인터페이스를 통한 타입 제한

package main

import "fmt"

type Adder interface {
	Add() int
}

// Calculator1 Add 함수만 가지는 구조체
type Calculator1 struct {
	a int
	b int
}

func (c Calculator1) Add() int {
	return c.a + c.b
}

// Calculator2 Minus 함수만 가지는 구조체
type Calculator2 struct {
	a int
	b int
}

func (c Calculator2) Minus() int {
	return c.a - c.b
}

func AddValues[T Adder](adder T) int {
	return adder.Add()
}

func main() {
	// Calculator 인스턴스를 생성
	calc := Calculator1{2, 3}

	// AddValues 함수를 호출하여 두 값의 합을 계산
	result := AddValues(calc)
	fmt.Println(result) // 5

	// Calculator2 인스턴스를 생성
	//calc2 := Calculator2{5, 3}
	//result2 := AddValues(calc2) // T (type Calculator2) does not satisfy Adder (missing method Add) 에러 발생
	//fmt.Println(result2)
}

 

  • Calculator1 구조체는 Adder 인터페이스를 구현하므로 AddValues 함수에 전달 가능
  • Calculator2 구조체는 Adder 인터페이스를 구현하지 않으므로 AddValues 함수에 전달 불가

 

package main

import "fmt"

type Number interface {
	int | float64
}

func Average[T Number](values []T) T {
	var sum T
	for _, v := range values {
		sum += v
	}
	return sum / T(len(values))
}

func main() {
	fmt.Println(Average([]int{1, 2, 3, 4, 5}))        // 3 (int)
	fmt.Println(Average([]float64{1.1, 2.2, 3.3}))    // 2.2 (float64)
	//fmt.Println(Average([]string{"apple", "banana"})) // string does not satisfy Number (string missing in int | float64) 에러 발생
}

 

 

 

참고:

https://go.dev/blog/intro-generics