在golang中没有内置的set,我们可以使用map[interface{}]bool
或者map[interface{}]struct{}
实现。
为了支持任意类型元素,我们可以使用空接口interface{},实现set这里使用struct{}
type exists struct{}
type set struct {
m map[interface{}]exists
}
基本的操作如下:
去调用Add函数添加一堆元素到set中
func NewSet(items ...interface{}) *set {
s := &set{}
s.m = make(map[interface{}]exists)
s.Add(items...)
return s
}
将元素列表插入到set中
func (s *set) Add(items ...interface{}) {
for _, item := range items {
s.m[item] = exists{}
}
}
删除指定元素
func (s *set) Remove(item interface{}) {
delete(s.m, item)
}
基本的map查询操作即可
func (s *set) Contains(item interface{}) bool {
_, ok := s.m[item]
return ok
}
func (s *set) Contains(item interface{}) bool {
_, ok := s.m[item]
return ok
}
func (s *set) Size() int {
return len(s.m)
}
最后聊一下为啥这里可以用struct{}?
因为你去比较两个struct{}时会发现是相等的。
例如:
s1 := struct{}{}
s2 := struct{}{}
fmt.Printf("s1 address:%p, s2 address:%p\n", &s1, &s2)
fmt.Println(s1 == s2)
此时输出:
s1 address:0x1190370, s2 address:0x1190370
true
可以看到地址一样,比较也相等, 空结构体大小多少呢
fmt.Println(unsafe.Sizeof(struct{}{}))
结果为0,精彩呀,不占用内存。放在map构造的set简直无敌,完成了下面两个工作:
上面set使用:
func main() {
s := NewSet("beijing", "beijing", "shanghai", 101)
s.Add(false)
}
本节完~