Go concurrent-safe, goroutine-safe, thread-safe queue
The package goconcurrentqueue offers a public interface Queue with methods for a queue. It comes with multiple Queue's concurrent-safe implementations, meaning they could be used concurrently by multiple goroutines without adding race conditions.
Execute
go get github.com/enriquebris/goconcurrentqueue
This package is compatible with all golang versions >= 1.7.x
Visit goconcurrentqueue at go.dev
FIFO: concurrent-safe auto expandable queue.
FixedFIFO: concurrent-safe fixed capacity queue.
The numbers for the following charts were obtained by running the benchmarks in a 2012 MacBook Pro (2.3 GHz Intel Core i7 - 16 GB 1600 MHz DDR3) with golang v1.12
package main
import (
"fmt"
"github.com/enriquebris/goconcurrentqueue"
)
type AnyStruct struct {
Field1 string
Field2 int
}
func main() {
queue := goconcurrentqueue.NewFIFO()
queue.Enqueue("any string value")
queue.Enqueue(5)
queue.Enqueue(AnyStruct{Field1: "hello world", Field2: 15})
// will output: 3
fmt.Printf("queue's length: %v\n", queue.GetLen())
item, err := queue.Dequeue()
if err != nil {
fmt.Println(err)
return
}
// will output "any string value"
fmt.Printf("dequeued item: %v\n", item)
// will output: 2
fmt.Printf("queue's length: %v\n", queue.GetLen())
}
package main
import (
"fmt"
"time"
"github.com/enriquebris/goconcurrentqueue"
)
func main() {
var (
fifo = goconcurrentqueue.NewFIFO()
done = make(chan struct{})
)
go func() {
fmt.Println("1 - Waiting for next enqueued element")
value, _ := fifo.DequeueOrWaitForNextElement()
fmt.Printf("2 - Dequeued element: %v\n", value)
done <- struct{}{}
}()
fmt.Println("3 - Go to sleep for 3 seconds")
time.Sleep(3 * time.Second)
fmt.Println("4 - Enqueue element")
fifo.Enqueue(100)
<-done
}
package main
import (
"context"
"fmt"
"time"
"github.com/enriquebris/goconcurrentqueue"
)
func main() {
var (
fifo = goconcurrentqueue.NewFIFO()
ctx, cancel = context.WithTimeout(context.Background(), 3*time.Second)
)
defer cancel()
fmt.Println("1 - Waiting for next enqueued element")
_, err := fifo.DequeueOrWaitForNextElementContext(ctx)
if err != nil {
fmt.Printf("2 - Failed waiting for new element: %v\n", err)
return
}
}
High level modules should not depend on low level modules. Both should depend on abstractions. Robert C. Martin
package main
import (
"fmt"
"github.com/enriquebris/goconcurrentqueue"
)
func main() {
var (
queue goconcurrentqueue.Queue
dummyCondition = true
)
// decides which Queue's implementation is the best option for this scenario
if dummyCondition {
queue = goconcurrentqueue.NewFIFO()
} else {
queue = goconcurrentqueue.NewFixedFIFO(10)
}
fmt.Printf("queue's length: %v\n", queue.GetLen())
workWithQueue(queue)
fmt.Printf("queue's length: %v\n", queue.GetLen())
}
// workWithQueue uses a goconcurrentqueue.Queue to perform the work
func workWithQueue(queue goconcurrentqueue.Queue) error {
// do some work
// enqueue an item
if err := queue.Enqueue("test value"); err != nil {
return err
}
return nil
}