질문의 역사:
Go는 기본적으로 Set 구조체를 제공하지 않지만, 고유한 요소와 작업해야 하는 경우가 자주 발생합니다. 최적의 구조체는 map[string]struct{}로, 여기서 키는 요소이며 빈 구조체는 "존재 마크"로 사용됩니다. 이는 빠른 membership 테스트를 위한 일반적인 패턴입니다.
문제:
내장된 Set이 없기 때문에 초보자들은 고유한 컬렉션을 올바르게 구현하는 것이 어렵다고 느낍니다. 또한, struct{}가 bool이나 int보다 값으로서 더 효율적인 이유를 이해할 필요가 있습니다.
해결책:
Go에서 Set을 구현하기 위해서는 map[string]struct{}를 사용합니다. 빈 구조체 struct{}는 메모리를 요구하지 않으며(zero-sized), map은 빠른 접근을 보장합니다. 예:
set := make(map[string]struct{}) set["foo"] = struct{}{} if _, ok := set["foo"]; ok { fmt.Println("존재") } delete(set, "foo")
주요 특징:
왜 slice/배열을 값으로 사용할 수 없나요?
slice/배열은 set으로 사용할 경우 요소 검색에 상수 시간 복잡도를 제공하지 않으며, 모든 값을 순회해야 하므로 느립니다.
map[string]struct{}와 map[string]bool의 차이는 무엇인가요?
map[string]bool은 더 많은 메모리를 차지합니다: 각 키마다 bool을 저장하는 반면, struct{}는 빈 타입으로 아무것도 할당하지 않습니다.
set := map[string]bool{"foo": true}
struct{} 대신 int를 사용할 수 있나요?
가능하지만, int는 항상 메모리를 차지합니다. struct{}는 만능입니다: "마크"(존재) 역할만 필요하다면 더 좋습니다.
set := map[string]int{"foo": 1} // 하지만 (키 -> 숫자)를 저장함
무지로 인해 고유한 IP 주소 집합을 위해 map[string]bool이 지정되었습니다. 결과적으로 수백만 개의 주소에서 메모리 사용량이 struct{}에 비해 두 배로 증가했습니다.
장점:
단점:
프로젝트에서 고유한 이메일을 저장하기 위해 map[string]struct{}를 사용했습니다. 부담이 줄어들고 더 빠르게 작동했으며, 값에 대해 거의 메모리를 사용하지 않았습니다.
장점:
단점: