golang,go,博客,开源,编程

初识golang-set

Published on with 0 views and 0 comments

golang-set 是一个常用的 Go 语言实现的集合(Set)数据结构库。集合是一个包含多个唯一元素的无序容器。在 Go 中,标准库并没有提供集合类型,因此很多开源库实现了集合的功能,golang-set 就是其中之一。它为 Go 提供了一个简单的实现,使得可以使用集合的功能,比如去重、并集、交集、差集等。

golang-set 简介

golang-set 是一个线程安全的集合类型,基于 Go 语言的内建 map 实现。它提供了一个高效且易于使用的集合 API,支持常见的集合操作(如添加、删除、检查元素等)。

该库的 GitHub 仓库地址为:https://github.com/deckarep/golang-set

以下是源码的基本结构和一些关键功能的分析。

1. 主要结构体:Set

type Set struct {
    m map[interface{}]struct{}
}

Set 结构体是 golang-set 的核心,包含一个字段 m,它是一个 map 类型,存储集合的元素。集合的元素被存储为 interface{} 类型,这样就可以存储任何类型的元素。而结构体的值是一个空结构体 struct{},这种方式的好处是空结构体不占用内存。

2. 创建新集合:NewSet

// NewSet creates a new set.
func NewSet() Set {
    return Set{m: make(map[interface{}]struct{})}
}

NewSet 函数用于创建一个新的空集合。内部使用了 make 函数来创建一个空的 map,用于存储集合中的元素。

3. 添加元素:Add

// Add adds an element to the set.
func (s *Set) Add(e interface{}) {
    s.m[e] = struct{}{}
}

Add 方法将一个元素添加到集合中。如果该元素已经存在于集合中,由于 map 键的唯一性,添加操作会自动忽略重复的元素。因此,集合保证了元素的唯一性。

4. 删除元素:Remove

// Remove removes an element from the set.
func (s *Set) Remove(e interface{}) {
    delete(s.m, e)
}

Remove 方法从集合中删除指定的元素。它使用 delete 函数从 map 中移除对应的键。

5. 判断元素是否存在:Contains

// Contains checks if the element exists in the set.
func (s *Set) Contains(e interface{}) bool {
    _, found := s.m[e]
    return found
}

Contains 方法用于检查集合中是否包含指定的元素。它通过访问 map 来判断元素是否存在,如果存在返回 true,否则返回 false

6. 获取集合大小:Size

// Size returns the number of elements in the set.
func (s *Set) Size() int {
    return len(s.m)
}

Size 方法返回集合中元素的数量,实际上是 map 中键的数量。

7. 清空集合:Clear

// Clear removes all elements from the set.
func (s *Set) Clear() {
    s.m = make(map[interface{}]struct{})
}

Clear 方法会清空集合中的所有元素。它通过重新分配一个新的空 map 来实现这一功能。

8. 迭代集合:Iter

// Iter returns a channel that can be used to iterate over the set.
func (s *Set) Iter() <-chan interface{} {
    ch := make(chan interface{})
    go func() {
        for e := range s.m {
            ch <- e
        }
        close(ch)
    }()
    return ch
}

Iter 方法返回一个可以用于迭代集合的通道。由于 Go 中的 map 并不是有序的,因此每次迭代时,元素的顺序是不确定的。

9. 集合操作:并集、交集、差集

并集(Union)

// Union returns a new set which is the union of the two sets.
func (s *Set) Union(other Set) Set {
    newSet := NewSet()
    for e := range s.m {
        newSet.Add(e)
    }
    for e := range other.m {
        newSet.Add(e)
    }
    return newSet
}

Union 方法返回两个集合的并集,它将两个集合中的所有元素合并到一个新的集合中。

交集(Intersection)

// Intersection returns a new set which is the intersection of the two sets.
func (s *Set) Intersection(other Set) Set {
    newSet := NewSet()
    for e := range s.m {
        if other.Contains(e) {
            newSet.Add(e)
        }
    }
    return newSet
}

Intersection 方法返回两个集合的交集,只包含两个集合中都有的元素。

差集(Difference)

// Difference returns a new set which is the difference between the two sets.
func (s *Set) Difference(other Set) Set {
    newSet := NewSet()
    for e := range s.m {
        if !other.Contains(e) {
            newSet.Add(e)
        }
    }
    return newSet
}

Difference 方法返回两个集合的差集,即只包含集合 s 中有而集合 other 中没有的元素。

10. 集合是否为空:IsEmpty

// IsEmpty checks if the set is empty.
func (s *Set) IsEmpty() bool {
    return len(s.m) == 0
}

IsEmpty 方法检查集合是否为空,返回一个布尔值。

11. 销毁集合:Destroy

// Destroy destroys the set and releases resources.
func (s *Set) Destroy() {
    s.m = nil
}

Destroy 方法销毁集合,释放其占用的内存资源。

12. 线程安全性

golang-set 的实现并不自动处理并发访问问题。因此,如果在多个 goroutine 中并发访问一个集合,程序需要通过外部同步机制来确保线程安全,例如使用 sync.Mutexsync.RWMutex 来锁定集合。

type ThreadSafeSet struct {
    mu sync.RWMutex
    set Set
}

func (s *ThreadSafeSet) Add(e interface{}) {
    s.mu.Lock()
    defer s.mu.Unlock()
    s.set.Add(e)
}

func (s *ThreadSafeSet) Remove(e interface{}) {
    s.mu.Lock()
    defer s.mu.Unlock()
    s.set.Remove(e)
}

func (s *ThreadSafeSet) Contains(e interface{}) bool {
    s.mu.RLock()
    defer s.mu.RUnlock()
    return s.set.Contains(e)
}

总结

golang-set 的核心设计是基于 Go 内置的 map 数据结构,它通过将元素作为键存储,实现了高效的集合操作,保证了集合中的元素唯一性。库中包含了常见的集合操作,如添加、删除、查找、并集、交集等,且操作简单易用。需要注意的是,golang-set 并不默认提供并发安全保障,如果需要在多线程环境中使用,程序员需要自行处理同步问题。


标题:初识golang-set
作者:mooncakeee
地址:http://blog.dd95828.com/articles/2025/01/07/1736226964330.html
联系:scotttu@163.com