«

Go 语言 Set 集合简单实现

Go 语言标准库中,没有 Set 实现,不过我们可以通过原生的 map 自己实现。

我们知道,Set 是一种集合类数据结构,可以用来存储一系列的值,这些值无顺序,且不能重复。

标准库中,map 可以用来存储 key-value 数据集合,key 默认无序,且不能重复,正好符合 set 的集合属性。

可以像这样定义一个类型的 set 结构:

var InterfaceSet map[interface{}]bool  
var IntSet       map[int]bool  
var StringSet    map[string]bool  

甚至可以把 map 中的 value 的值用 struct{} 代替,stuct{} 是 0 个字节,bool 是 1 个字节。

var InterfaceSet map[interface{}]struct{}  
var IntSet       map[int]struct{}  
var StringSet    map[string]struct{}  

以一个 string set 为例,看看如何操作 set

// 声明一个 string set
s := make(map[string]struct{})

// 在 set 中添加元素
s["Bingo"] = struct{}{}  
s["Huang"] = struct{}{}

// 在 set 中查询某个元素是否存在(判断 exist 为 true 还是 false)
_, exist := s["Bingo"]

// 在 set 中删除某个元素
delete(s, "Bingo")

// 遍历 set 中所有元素
for v := range s {  
    fmt.Println(v)
}

以上是最简单的实现版本,但是不够直观,我们可以封装成更友好的方式,提供增删改查方法,如下:

package main

import (  
    "fmt"
)

type set struct {  
    m map[string]struct{}
}

func NewSet()  *set {  
    s := &set{}
    s.m = make(map[string]struct{})
    return s
}

func (s *set) Add(v string) {  
    s.m[v] = struct{}{}
}

func (s *set) Contains(v string) bool {  
    _, c := s.m[v]
    return c
}

func (s *set) Remove(v string)  {  
    delete(s.m, v)
}

func main() {  
    s := NewSet()

    s.Add("Bingo")
    s.Add("Huang")

    fmt.Println(s.Contains("Bingo"))
    fmt.Println(s.Contains("Huang"))

    s.Remove("Bingo")
    fmt.Println(s.Contains("Bingo"))
}

我把这段代码放在了 GitHubGist 中 golang-set

如果你还要考虑线程安全,或者更地道的实现,可以看看这个 Github仓库,还被 Docker、Kubernetes用到了。

分享