Fall in IT.

Go 1.18버전부터 추가 된 generic 사용해보기 본문

프로그래밍언어/Golang

Go 1.18버전부터 추가 된 generic 사용해보기

D.Y 2022. 5. 2. 15:53

 

안녕하세요.

 

오늘은 Go 1.18 버전에서 추가 된 generic을 사용해보도록 하겠습니다.

 

Generic에 대한 개념은 여기서 확인해주시기 바랍니다.

 

 

Generic 사용 전 (source code)

interface를 사용하여 스택을 구현한 경우

package main

import "fmt"

type stack struct {
	data []interface{}
}

type Stack interface {
	Push(data interface{})
	Pop() interface{}
	Get() []interface{}
}

func New() Stack {
	return &stack{
		data: []interface{}{},
	}
}

func (s *stack) Push(data interface{}) {
	fmt.Println("push data: ", data)
	s.data = append(s.data, data)
}

func (s *stack) Pop() interface{} {
	lastData := s.data[len(s.data)-1]
	fmt.Println("pop data: ", lastData)

	s.data = s.data[:len(s.data)-1]
	return lastData
}

func (s *stack) Get() []interface{} {
	return s.data
}

func main() {
	stack := New()
	stack.Push("10")
	stack.Push("20")
	stack.Push("30")  // string이 아닌 어떤 타입도 넣어도 에러가 발생하지 않는다.
	stack.Push("40")
	stack.Pop()

	response := stack.Get()  // response 배열 안에 담긴 데이터의 타입을 알 수 없다.
	fmt.Println(response...)
}

문제점

  1. 스택에 어떤 타입의 데이터를 넣어도 에러가 발생하지 않는다.
    즉, string 타입의 원소만 들어가는 스택으로 사용하고 싶은경우 실수로 int형 타입의 원소가 들어왔을때 컴파일 단계에서 알수가 없다.
  2. 스택의 데이터를 조회 했을때 해당 원소가 어떤 타입인지 알 수 없다.

 

Generic 사용 후 (source code)

generic을 사용하여 스택을 구현한 경우

package main

import (
	"fmt"
)

type stack[T any] struct {
	data []T
}

type Stack[T any] interface {
	Push(data T)
	Pop() T
	Get() []T
}

func New[T any]() Stack[T] {
	return &stack[T]{
		data: []T{},
	}
}

func (s *stack[T]) Push(data T) {
	fmt.Println("push data: ", data)
	s.data = append(s.data, data)
}

func (s *stack[T]) Pop() T {
	lastData := s.data[len(s.data)-1]
	fmt.Println("pop data: ", lastData)

	s.data = s.data[:len(s.data)-1]
	return lastData
}

func (s *stack[T]) Get() []T {
	return s.data
}

func main() {
	intStack := New[int]()
	intStack.Push(1)
	intStack.Push(2)
	intStack.Push(3)
	intStack.Push(4)
	intStack.Pop()

	response := intStack.Get()
	fmt.Println(response)

	stringStack := New[string]()
	stringStack.Push("a")
	stringStack.Push(100)   // Error - 타입이 맞지않기 때문에 컴파일 단계에서 에러 발생
	stringStack.Push("c")
	stringStack.Push("d")
	stringStack.Pop()

	response2 := stringStack.Get()
	fmt.Println(response2)   // response2에 담긴 원소는 무조건 string 타입이다
}

generic을 사용함으로써 위에서 발생한 문제를 해결할 수 있다.

 

 

결과

generic을 사용함으로써 아래와 같은 장점이 생겼다!

  1. 컴파일 단계에서 타입 체크가 가능하여 안정적으로 코딩할 수 있다.
  2. 사용하는 시점에 타입을 지정할 수 있기 때문에 명확하게 코딩할 수 있다.

 

 

 

Comments