Go语言使用Set

212 阅读1分钟

新到Go语言的伙伴当认识到Go没有Set这种存储唯一值的内置数据结构。但是利用Map也不难实现。由于Go的泛型没有像一样Java一样完善,因此你就得对每种类型单独实现Set来拒绝重复,这样显得有些无聊。

那么我们看一下以下解决方式:

使用空结构体 struct{} 可以节省内存,一般作为占位符使用,表明这里并不需要一个值

fmt.Println(unsafe.Sizeof(struct{}{})) // 0

那么我们把空结构体的这个特性运用到实现Set上:

// UniqStr 返回一个切片,该切片包含传入的字符串切片中去重的结果。
func UniqStr(col []string) []string {
    m := map[string]struct{}{}
   for _, v := range col {
     if _, ok := m[v]; !ok {
      m[v] = struct{}{}
     }
    }
   list := make([]string, len(m))
   i := 0
   for v := range m {
   list[i] = v
    i++
   }
 return list
} 

或者也可以提前声明为别名:

type Set map[string]struct{}

type Set map[string]struct{}func main(){
	set := make(Set)
	for _, item := range []string{"A", "A", "B", "C"} {
		set[item] = struct{}{}
	}
	fmt.Println(len(set)) // 3
	if _, ok := set["A"]; ok {
		fmt.Println("A exists") // A exists
	}
}

空结构体也可以用在信道(channel)通信时我们只需要一个信号,但不需要传递值的情况:

func main() {
   ch := make(chan struct{}, 1)
   go func() {
      <-ch      // do something
   }()
   ch <- struct{}{}
   // ...}