Skip to main content

Golang에는 Set이 없어요...

· 2 min read

image

Go 언어는 기본적으로 set 데이터 타입을 제공하지 않습니다.

그래서 편리하게 사용하던 set을 사용하고 싶다면, 직접 구현해야 합니다!

막상 갑자기 직접 구현하려니 마음이 답답한데, Go에서 제공하는 Map 데이터 타입을 이용해 쉽게 구현할 수 있습니다.

Map은 키, 값을 한쌍으로 갖기 때문에, 키가 중복되면 안됩니다. 

이 원리를 이용하면 쉽게 구현됩니다.

map[type]struct 를 이용하여 구현하게 됩니다. struct 는 빈 구조체로서 메모리를 차지하지 않게 됩니다. 

그래서 map[type]struct 를 이용하면 값 없이 키만 저장할 때 사용하기에 제격입니다.

이 때, type에 대해 T comparable을 이용하면 여러 타입의 Set을 소화할 수 있도록 만들 수 있습니다.

아래는 구현한 내용입니다. 

package main

type Set[T comparable] map[T]struct{}

func NewSet[T comparable](values []T) Set[T] {
set := make(Set[T])
set.Add(values)
return set
}

func (s Set[T]) Add(values []T) {
for _, value := range values {
s[value] = struct{}{}
}
}

func (s Set[T]) Remove(value T) {
delete(s, value)
}

func (s Set[T]) Contains(value T) bool {
_, exists := s[value]
return exists
}

func (s Set[T]) Size() int {
return len(s)
}

func (s Set[T]) ToSlice() []T {
slice := make([]T, 0, len(s))
for value := range s {
slice = append(slice, value)
}
return slice
}

간단히 사용하려면 사실 설명을 보지 않고 바로 복붙해서 사용해도 됩니다.

NewSet은 slice(array)를 입력 받아 Add를 통해 Set 구조체에 넣어줍니다.

Add도 slice(array)를 입력 받아 해당 Set 구조체에 value를 키값으로 한 빈 구조체를 설정해 줍니다.

Remove는 키 값을 제거해 주고 Contains는 키 값이 존재하는지 확인해 true, false로 반환하고 Size는 키의 개수를 확인해 줍니다.

그리고 나중에 다시 slice(array)로 변경하고자 할 때는 ToSlice를 이용해 slice로 변환합니다.

아래는 실제 사용 예시입니다.

package main

func main() {
// 빈 Set 생성 후 슬라이스로 추가
s := NewSet([]int{1, 2, 3}) // 여러 값 추가

// 추가적인 값들을 슬라이스로 추가
moreValues := []int{4, 5, 6}
s.Add(moreValues) // 슬라이스를 전달하여 추가

fmt.Println(s.Contains(1)) // true
fmt.Println(s.Contains(6)) // true
fmt.Println(s.Contains(7)) // false

fmt.Println(s.Size()) // 6

s.Remove(1)
fmt.Println(s.Contains(1)) // false

// 현재 Set의 값을 배열로 변환하여 출력
fmt.Println(s.ToSlice()) // [2 3 4 5 6]
}

Set을 사용하는 것은 본인이 편리한 방식으로 커스텀 해서 구현해 사용해도 됩니다.

도움이 되었으면 좋겠네요. 감사합니다!