Go 实现队列
...大约 1 分钟
需求
用 Go 实现一个固定大小的队列结构,当队列中进入新数据时判断,如果超过限制则淘汰最早的数据,使队列大小始终不超过最大限制。
1. 实现
缓存代码queue.go
package queue
import (
"go.uber.org/zap"
"math"
"time"
)
type queue []time.Time
var GlobalReqLimit = queue{}
// 最大 5 个元素
const maxSize = 5
//加入元素
//这里需要使用指针
func (q *queue) Push(v time.Time) {
// 队列是否已满
if q.IsFull() {
// 对比第一个时间,如果在 1 分钟内则等待
first := q.Offer()
sub := int(math.Ceil(time.Now().UTC().Sub(first).Seconds()))
for sub <= 60 {
logger.Info("request rate limit, wait a moment", zap.Int("second", 60-sub))
time.Sleep(time.Second)
sub = int(math.Ceil(time.Now().UTC().Sub(first).Seconds()))
}
q.Pop()
}
*q = append(*q, v)
}
// 弹出第一个元素
func (q *queue) Pop() time.Time {
head := (*q)[0]
*q = (*q)[1:]
return head
}
// 查看第一个元素,但不弹出
func (q *queue) Offer() time.Time {
return (*q)[0]
}
//判断是否为空
func (q *queue) IsEmpty() bool {
return q.Size() == 0
}
//判断是否已满
func (q *queue) IsFull() bool {
return q.Size() == maxSize
}
func (q *queue) Size() int {
return len(*q)
}
测试queue_test.go
package queue
import (
"testing"
"time"
)
func TestQueue(t *testing.T) {
GlobalReqLimit.Push(time.Now().UTC())
println(GlobalReqLimit.Size())
GlobalReqLimit.Offer()
println(GlobalReqLimit.Size())
}
测试结果:
=== RUN TestQueue
1
1
--- PASS: TestQueue (0.00s)
PASS