使用Golang的channel实现一个并发安全的队列,支持阻塞和非阻塞,实现入队和出队方法。
package queue
import "errors"
type BlockQueue struct {
data chan interface{}
cap int
timeout int
}
func NewBlockQueue(cap, timeout int) *BlockQueue {
if cap <= 0 {
return nil
}
queue := new(BlockQueue)
queue.data = make(chan interface{}, cap)
queue.cap = cap
queue.timeout = timeout
return queue
}
func (bq *BlockQueue) Len() int {
return len(bq.data)
}
func (bq *BlockQueue) Cap() int {
return bq.cap
}
func (bq *BlockQueue) Enqueue(val interface{}) error {
select {
case bq.data <- val:
return nil
case time.After(time.Duration(bq.timeout) * time.Second):
return errors.New("Enqueue timeout.")
}
}
func (bq *BlockQueue) Dequeue() (interface{}, error) {
select {
case data := <- bq.data
return data, nil
case time.After(time.Duration(bq.timeout) * time.Second):
return nil, errors.New("Dequeue timeout.")
}
}
type NonBlockQueue struct {
data chan interface{}
cap int
}
func NewNonBlockQueue(cap int) *NonBlockQueue {
if cap <= 0 {
return nil
}
queue := new(NonBlockQueue)
queue.data = make(chan interface{}, cap)
queue.cap = cap
return queue
}
func (nq *NonBlockQueue) Len() int {
return len(nq.data)
}
func (nq *NonBlockQueue) Cap() int {
return nq.cap
}
func (nq *NonBlockQueue) Enqueue(val interface{}) error {
select {
case nq.data <- val:
return nil
default:
return errors.New("Queue is full.")
}
}
func (nq *NonBlockQueue) Dequeue() (interface{}, error) {
select {
case data := <- nq.data
return data, nil
default:
return nil, errors.New("Queue is empty.")
}
}