golang container/list 实现队列并控制并发
container/list
主要方法
golang的 container/list 实现了一个双向链表,可能你要问list和slice的区别是什么后续一一道来:
- func New() *List{}
初始化一个列表,返回类型为一个list对象 - func (l List) Init() List{}
初始化此链表,将元素全部清空 - func (l *List) Len() int{}
返回链表的长度,返回值类型为 int - func (l List) Back() Element{}
返回链表的最后一个元素,返回类型为列表中的元素 - func (l List) Front() Element{}
返回链表的第一个元素,返回类型为列表中的元素 - func (l List) PushFront(v interface{}) Element{}
PushFront在列表的前面插入一个值为v的新元素e并返回e - func (l List) PushBack(v interface{}) Element{}
PushBack在列表l的后面插入一个值为v的新元素e并返回e - func (l List) Remove(e Element) interface{}{}
如果e是列表l的元素,则删除从l中删除e。它返回元素值e.Value。元素不能为零。 - 还提供了链表合并,元素移动,元素插入 元素移除等更多方法,请参考: https://pkg.go.dev/container/list
与slice的区别
slice 的底层是数组实现的,而list则是一个双向链表,众所周知,数组的优势在于索引快,遍历快,而链表的优势在于 插入快、删除快,list适合于那些频繁插入删除操作的场景。而slice适合于那些多次查询的场景。
实现一个先进先出的队列
package main
import (
"container/list"
"fmt"
"sync"
"time"
)
type customQueue struct {
queue *list.List
}
var (
Queue *customQueue
lock sync.Mutex
)
func init() {
Queue = &customQueue{
queue: list.New(),
}
}
func (c *customQueue) Enqueue(value map[string]interface{}) {
defer lock.Unlock()
lock.Lock()
c.queue.PushBack(value)
}
func (c *customQueue) Dequeue() (map[string]interface{}, error) {
defer lock.Unlock()
lock.Lock()
if c.queue.Len() > 0 {
ele := c.queue.Front()
if val, ok := ele.Value.(map[string]interface{}); ok {
c.queue.Remove(ele)
return val, nil
}
fmt.Println("Queue Datatype is incorrect", c.queue.Front().Value)
c.queue.Remove(ele)
return map[string]interface{}{}, fmt.Errorf("Peep Error: Queue Datatype is incorrect")
}
return map[string]interface{}{}, fmt.Errorf("Peep Error: Queue is empty")
}
func (c *customQueue) Size() int {
return c.queue.Len()
}
func (c *customQueue) Empty() bool {
return c.queue.Len() == 0
}
func main() {
var postjson = map[string]interface{}{
"name": "anber",
"age": "18",
}
//入队
Queue.Enqueue(postjson)
// 打印队列长度
fmt.Println("queue Size:", Queue.Size())
// 循环出队
for {
if Queue.Size() == 0 {
fmt.Println("queue Size is 0")
time.Sleep(time.Duration(3) * time.Second)
}
for Queue.Size() > 0 {
frontVal, err := Queue.Dequeue()
if err != nil {
fmt.Println("queue front err:", err)
}
fmt.Println("Front: ", frontVal)
if err != nil {
fmt.Println("Dequeue err:", err)
}
fmt.Println("queue Size:", Queue.Size())
}
}
}
运行结果
queue Size: 1
Front: map[age:18 name:anber]
queue Size: 0
queue Size is 0