欢迎来到尧图网

客户服务 关于我们

您的位置:首页 > 教育 > 培训 > Go 不可重复协程安全队列

Go 不可重复协程安全队列

2025/5/23 0:43:15 来源:https://blog.csdn.net/qq_52160611/article/details/145330782  浏览:    关键词:Go 不可重复协程安全队列

代码实现

package dataStructimport ("errors""sync"
)// GenericQueue 是一个支持泛型的不可重复队列,具有最大长度限制
// T 是泛型参数
type GenericQueue[T comparable] struct {items   map[T]struct{} // 使用 map 来存储元素order   []T            // 使用切片来记录元素的顺序lock    sync.RWMutex   // 读写锁,保证并发安全maxSize int            // 最大队列长度
}// NewGenericQueue 创建一个新的泛型队列,并指定最大长度
func NewGenericQueue[T comparable](maxSize int) *GenericQueue[T] {return &GenericQueue[T]{items:   make(map[T]struct{}), // 初始化 items maporder:   []T{},                // 初始化 order 切片maxSize: maxSize,              // 设置最大长度}
}// Add 添加元素到队列
// 如果队列已满,默认移除最旧的元素来腾出空间
func (q *GenericQueue[T]) Add(item T) error {q.lock.Lock()         // 加写锁,防止并发修改defer q.lock.Unlock() // 解锁// 判断元素是否已经存在if _, exists := q.items[item]; exists {return errors.New("item already exists in the queue")}// 如果队列已满,移除最旧的元素if len(q.order) >= q.maxSize {return errors.New("Out of length Queue ")}// 将元素添加到 map 中,标记该元素已存在q.items[item] = struct{}{}// 将元素添加到队列顺序中q.order = append(q.order, item)return nil
}// Remove 删除队列中的指定元素
// 如果元素不存在,则返回错误
func (q *GenericQueue[T]) Remove(item T) error {q.lock.Lock()         // 加写锁,防止并发修改defer q.lock.Unlock() // 解锁// 判断元素是否存在if _, exists := q.items[item]; !exists {return errors.New("item not found in the queue")}// 从 map 中删除该元素delete(q.items, item)// 从顺序切片中删除该元素for i, v := range q.order {if v == item {q.order = append(q.order[:i], q.order[i+1:]...) // 删除指定位置的元素break}}return nil
}// Update 修改队列中的元素
// 如果元素不存在,则返回错误
func (q *GenericQueue[T]) Update(oldItem, newItem T) error {q.lock.Lock()         // 加写锁,防止并发修改defer q.lock.Unlock() // 解锁// 判断 oldItem 是否存在if _, exists := q.items[oldItem]; !exists {return errors.New("old item not found in the queue")}// 判断 newItem 是否已存在if _, exists := q.items[newItem]; exists {return errors.New("new item already exists in the queue")}// 从 map 中删除 oldItem,并添加 newItemdelete(q.items, oldItem)q.items[newItem] = struct{}{}// 更新顺序切片中的 oldItem 为 newItemfor i, v := range q.order {if v == oldItem {q.order[i] = newItembreak}}return nil
}// Contains 查询队列中是否存在指定元素
func (q *GenericQueue[T]) Contains(item T) bool {q.lock.RLock()         // 加读锁,防止并发修改defer q.lock.RUnlock() // 解锁_, exists := q.items[item]return exists
}// Traverse 遍历队列中的元素
func (q *GenericQueue[T]) Traverse() []T {q.lock.RLock()         // 加读锁,防止并发修改defer q.lock.RUnlock() // 解锁// 返回元素的副本,防止并发问题result := make([]T, len(q.order))copy(result, q.order)return result
}// Iterator 返回一个可以用于 for range 的通道
func (q *GenericQueue[T]) Iterator() <-chan T {ch := make(chan T)go func() {q.lock.RLock()         // 加读锁,防止并发修改defer q.lock.RUnlock() // 解锁defer close(ch)        // 关闭通道for _, item := range q.order {ch <- item}}()return ch
}

介绍

1. 支持泛型

  • 队列支持泛型参数 T,因此可以存储任何类型的元素,只要该类型是 comparable(可比较的)。这意味着你可以使用这个队列来存储数字、字符串、结构体等类型的数据。

2. 不可重复

  • 队列内部通过 map 来存储元素,因此它自动确保元素的唯一性。也就是说,队列中不会有重复的元素。

3. 顺序存储

  • 使用切片 order 来记录元素的顺序,保证在遍历时元素的顺序是加入队列时的顺序。

4. 并发安全

  • 队列实现了并发控制,使用了 sync.RWMutex 读写锁来保证在多线程环境下的安全操作。多个 goroutine 可以并发地读取队列,或者一个 goroutine 可以安全地修改队列。

5. 常见操作

  • 添加元素(Add): 如果元素已经存在,则无法再次添加;如果队列已满,返回 Out of length Queue 错误,不会自动移除最旧元素
  • 删除元素(Remove): 可以删除队列中的某个元素。
  • 更新元素(Update): 可以将队列中的某个元素更新为新的元素,前提是新元素不存在。
  • 检查元素是否存在(Contains): 查询队列中是否包含某个元素。
  • 遍历队列(Traverse): 返回队列中所有元素的副本,供遍历使用。
  • 支持 for range 遍历: 通过 Iterator 方法,队列可以返回一个只读通道,可以直接在 for range 循环中使用。

6. 适用场景

  • 适用于需要按顺序处理且确保元素唯一的场景,例如任务队列、事件队列等。
  • 适用于并发环境,确保多个操作的安全性。

示例用法:

 

type Ta struct {Name string
}func main() {impl := test.XueTestingImplimpl.StartTest()// 示例:创建一个支持整数的泛型队列queue := dataStruct.NewGenericQueue[Ta](1024)queue.Add(Ta{Name: "xzm"})queue.Add(Ta{Name: "yyds"})queue.Add(Ta{Name: "id"})//修改queue.Update(Ta{Name: "id"}, Ta{Name: "ids"})//遍历for ta := range queue.Iterator() {fmt.Println(ta)}//查找contains := queue.Contains(Ta{Name: "yyds",})//删除queue.Remove(Ta{Name: "yyds",})fmt.Println(contains)fmt.Println(queue)fmt.Println(queue.Traverse())impl.EndTest()
}

版权声明:

本网仅为发布的内容提供存储空间,不对发表、转载的内容提供任何形式的保证。凡本网注明“来源:XXX网络”的作品,均转载自其它媒体,著作权归作者所有,商业转载请联系作者获得授权,非商业转载请注明出处。

我们尊重并感谢每一位作者,均已注明文章来源和作者。如因作品内容、版权或其它问题,请及时与我们联系,联系邮箱:809451989@qq.com,投稿邮箱:809451989@qq.com

热搜词