Go 相当于 GCD 串行调度队列

Go equivalent of GCD serial dispatch queue

是否有 Go 相当于 Apple 的 GCD 串行调度队列?

目前我只找到了一个解决方案,就是通道函数。

work := make(chan func()) 

我将有一个函数从这个频道接收并调用接收到的函数。这些函数必须按 FIFO 顺序执行。

在 Go 中是否有更好的方法或结构来执行此操作?

这应该没有什么区别,但我希望将 SQL 查询排队到 FIFO 中的 运行。

像这样的东西应该可行,但是我不熟悉 GCD 的工作原理,所以我可能会偏离。

func main() {
    q := NewQueue(10) // the size is mainly so it wouldn't block, you can play with that to your liking.
    var wg sync.WaitGroup
    for i := 0; i < 10; i++ {
        wg.Add(1)
        i := i
        q <- func() { log.Println("i =", i); wg.Done() }
    }
    wg.Wait()
    close(q)
}

func NewQueue(size int) (q chan func()) {
    q = make(chan func(), size)
    go func() {
        for fn := range q {
            fn()
        }
    }()
    return
}

playground

@OneOfOne,接近但不完全。

我最终在 Go 中实现了串行调度队列 here

它基本上是一个 go 例程,阻塞在 func() 类型的 channel 上并运行按顺序传递的函数。

实施:

//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
}

用法:(演示以正确的顺序写入字符串)

//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);
    }
}

希望这对遇到同样问题的人有所帮助!