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
}
@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);
}
}
希望这对遇到同样问题的人有所帮助!
是否有 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
}
@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);
}
}
希望这对遇到同样问题的人有所帮助!