Search code examples
sqlgoqueuegrand-central-dispatch

Go equivalent of GCD serial dispatch queue


Is there Go equivalent of Apple's GCD serial dispatch queue?

So far I have only found a solution that is a channel of functions.

work := make(chan func()) 

I would have a function receive from this channel and call the received functions. The functions must be executed in FIFO order.

Is there a better method or structure to do this in Go?

This shouldn't make a difference but I am looking to queue SQL queries to run in FIFO for this.


Solution

  • @OneOfOne, it was close but not quite.

    I ended up making a Serial Dispatch Queue implementation in Go available here.

    It is basically a go routine that blocks on a channel of type func() and runs the functions that are passed in order.

    Implementation:

    //Package serialqueue provides a serial queue for functions. 
    //Queue items are processed in First In First Out (FIFO) order. 
    package serialqueue
    
    //New returns a new serial queue.
    //Enqueue items like queueObj <- func() {doWork(data)}
    func New() chan func() {
        //create channel of type function
        var queue = make(chan func())
    
        //spawn go routine to read and run functions in the channel
        go func() {
            for true {
                nextFunction := <-queue
                nextFunction()
            }
        }()
    
        return queue
    }
    

    Usage: (demonstrating writing to a string in the correct order)

    //Package serialqueue provides provides tests for github.com/ansonl/serialqueue. 
    package serialqueue_test
    
    import (
        "testing"
        "fmt"
        "sync"
        "github.com/ansonl/serialqueue"
        )
    
    func TestQueue(t *testing.T) {
        //Create new serial queue
        queue := serialqueue.New()
    
        //Number of times to loop
        var loops = 100
    
        //Queue output will be added here
        var queueOutput string
    
        //WaitGroup for determining when queue output is finished
        var wg sync.WaitGroup
    
        //Create function to place in queue
        var printTest = func(i int) {
            queueOutput = fmt.Sprintf("%v%v",queueOutput, i)
            wg.Done()
        }
    
        //Add functions to queue
        var i int;
        for i=0;i<loops;i++ {
            wg.Add(1)
            t:=i
            queue <- func() {printTest(t)}
        }
    
        //Generate correct output
        var correctOutput string
        for i=0;i<loops;i++ {
            correctOutput = fmt.Sprintf("%v%v", correctOutput, i)       
        }
    
        //Wait until all functions in queue are done
        wg.Wait()
    
        //Compare queue output with correct output
        if queueOutput != correctOutput {
            t.Errorf("Serial Queue produced %v, want %v", queueOutput, correctOutput);
        }
    }
    

    Hope this helps someone with the same issue!