Golang 简单的FIFO队列实现


原文地址声明:https://blog.csdn.net/qq_23179075/article/details/118191460

定义队列操作函数接口 IQueue

type IQueue interface {
    //Push 入队
    Push(data IData)
    
    //Pushs 一次性入队多个数据
    Pushs(data []IData)

    //Pop 出队
    Pop() IData

    //Get 获取队列中 index 位子的data
    Get(index int) IData

    //Set 设置队列中 index 位子的data
    Set(index int, data IData) error

    //Remove 设置队列中 index 位子的data
    Remove(index int) IData

    //RemoveAll 移除队列中的所有数据
    RemoveAll()

    //Size 当前队列大小
    Size() int

    //All 队列中的所有数据
    All() []IData

    //FindIndex 获取call返回为 true 第一个 index位子
    FindIndex(call func(item IData) bool) int
}

预留 IData 数据接口

type IData interface{}

实现 BQueue


type BQueue struct {
    Datas []IData
    mutex sync.Mutex
}

//NewQueueFromDatas 通过data输出生成队列
func NewQueueFromDatas(datas []IData) *BQueue {
    return &BQueue{Datas: datas}
}

//NewBQueue 初始化队列
func NewBQueue() *BQueue {
    return &BQueue{Datas: []IData{}}
}

func (b *BQueue) Push(data IData) {
    b.mutex.Lock()
    defer b.mutex.Unlock()

    b.Datas = append(b.Datas, data)
}
func (b *BQueue) Pushs(data []IData) {
    b.mutex.Lock()
    defer b.mutex.Unlock()

    b.Datas = append(b.Datas, data...)
}

func (b *BQueue) Pop() IData {
    b.mutex.Lock()
    defer b.mutex.Unlock()

    if len(b.Datas) <= 0 {
        return nil
    }

    var data = b.Datas[0]
    b.Datas = b.Datas[1:]
    return data
}

func (b *BQueue) Get(index int) IData {
    b.mutex.Lock()
    defer b.mutex.Unlock()

    if len(b.Datas) <= 0 {
        return nil
    }
    if index < 0 || index >= len(b.Datas) {
        return nil
    }
    return b.Datas[index]
}

func (b *BQueue) Set(index int, data IData) error {
    b.mutex.Lock()
    defer b.mutex.Unlock()

    if index < 0 || index >= len(b.Datas) {
        return fmt.Errorf(`index range of values [0,%v],index=%v`, len(b.Datas), index)
    }
    b.Datas[index] = data
    return nil
}

func (b *BQueue) Remove(index int) IData {
    b.mutex.Lock()
    defer b.mutex.Unlock()

    if len(b.Datas) == 0 {
        return nil
    }
    if index < 0 || index >= len(b.Datas) {
        return nil
    }

    data := b.Datas[index]
    b.Datas = append(b.Datas[:index], b.Datas[index+1:]...)
    return data
}

func (b *BQueue) RemoveAll() {
    b.mutex.Lock()
    defer b.mutex.Unlock()

    b.Datas = make([]IData, 0)
}

func (b *BQueue) Size() int {
    b.mutex.Lock()
    defer b.mutex.Unlock()

    return len(b.Datas)
}

func (b *BQueue) All() []IData {
    return b.Datas
}

func (b *BQueue) FindIndex(call func(item IData) bool) int {
    b.mutex.Lock()
    defer b.mutex.Unlock()

    for i, data := range b.Datas {
        if call(data) {
            return i
        }
    }
    return -1
}

测试

package queue

import (
    "fmt"
    "testing"
)

type BData struct {
    name string
    age  int
}

func TestBQueue(t *testing.T) {
    datas := []IData{
        &BData{name: "aaa", age: 12},
        &BData{name: "bbbb", age: 11},
    }
    queue := NewQueueFromDatas(datas)

    queue.Push(&BData{name: "CCC", age: 2})
    queue.Push(&BData{name: "DDD", age: 2})
    queue.Pushs([]IData{
        &BData{name: "EEE", age: 12},
        &BData{name: "FFF", age: 11},
    })

    err := queue.Set(2, &BData{name: "Haha", age: 3})
    if err != nil {
        fmt.Println(err)
    }

    err = queue.Set(10, &BData{name: "Haha", age: 3})
    if err != nil {
        fmt.Println("queue.Set(10): ", err)
    }

    for _, data := range queue.All() {
        fmt.Print(data, ",")
    }
    fmt.Println()

    index := queue.FindIndex(func(item IData) bool {
        return item.(*BData).name == "EEE"
    })

    fmt.Println("queue.FindIndex(EEE): ",index)

    fmt.Println("queue.Get(10): ", queue.Get(10))
    fmt.Println("queue.Get(2): ", queue.Get(2))
    fmt.Println("queue.Pop(): ", queue.Pop())
    fmt.Println("queue.Get(2): ", queue.Get(2))
    fmt.Println("queue.Pop(): ", queue.Pop())
    fmt.Println("queue.Pop(): ", queue.Pop())
    fmt.Println("queue.Pop(): ", queue.Pop())
    fmt.Println("queue.Size(): ", queue.Size())
    fmt.Println("queue.Pop(): ", queue.Pop())
    fmt.Println("queue.Pop(): ", queue.Pop())
    fmt.Println("queue.Pop(): ", queue.Pop())
}
=== RUN   TestBQueue
queue.Set(10):  index range of values [0,6],index=10
&{aaa 12},&{bbbb 11},&{Haha 3},&{DDD 2},&{EEE 12},&{FFF 11},
queue.FindIndex(EEE):  4
queue.Get(10):  
queue.Get(2):  &{Haha 3}
queue.Pop():  &{aaa 12}
queue.Get(2):  &{DDD 2}
queue.Pop():  &{bbbb 11}
queue.Pop():  &{Haha 3}
queue.Pop():  &{DDD 2}
queue.Size():  2
queue.Pop():  &{EEE 12}
queue.Pop():  &{FFF 11}
queue.Pop():  
--- PASS: TestBQueue (0.00s)
PASS