Skip to content

Instantly share code, notes, and snippets.

@christophberger
Last active August 29, 2015 14:18
Show Gist options
  • Save christophberger/ec8e28d06d322e1a9667 to your computer and use it in GitHub Desktop.
Save christophberger/ec8e28d06d322e1a9667 to your computer and use it in GitHub Desktop.
GoAndWait (go generate test, using reusee/ccg)
// Package concurrent contains a set of functions that encapsulate useful concurrency techniques.
// Use ccg to substitute appropriate types and to rename generic functions as desired.
// E.g., //go:generate ccg -f concurrent -t T=int -o concurrent.go
package concurrent
type T interface{}
// GoAndWait receives a slice of items and a function that receives an item,
// and calls this function concurrently for each item on the list.
// It waits for all gorountines to finish before returning.
// Use this function if:
// * each item can be processed independently of the other items,
// * all items must be processed before the list can be used in the next step.
// GoAndWait is especially useful if the worker function might have to wait for resources.
func GoAndWait(wl []*T, wf func(*T)) {
done := make(chan bool)
for _, w := range wl {
go func(item *T) {
wf(item)
done <- true
}(w)
}
for range wl {
<-done
}
}

GoAndWait

  • Tests code generation using ccg (reusee/ccg).
  • Encapsulates a concurrency pattern.

GoAndWait wraps a common concurrency pattern into a generic function:

  • The items of a list shall be processed concurrently
  • The main routine must wait until all items have been processed

Usually this is done by setting up a back channel, spawning n goroutines for n list items, and then reading n items from the back channel. Each goroutine must send an item to the back channel when done.

GoAndWait encapsulates this pattern, thus reducing code repetition.

Generate code from this template by running:

ccg -f concurrent -t T=int -o concurrent.go
//go:generate ccg -f concurrent -t T=WorkItem -o goandwait.go
package main
import (
"fmt"
"strings"
)
type WorkItem struct {
data string
result string
err error
}
func worker(i *WorkItem) {
item := (*WorkItem)(i)
item.result = strings.ToTitle(item.data)
item.err = nil
}
func main() {
workList := []*WorkItem{
{data: "first title"},
{data: "second title"},
{data: "third title"},
}
GoAndWait(workList, worker)
fmt.Println(workList[0].result)
fmt.Println(workList[1].result)
fmt.Println(workList[2].result)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment