Created
September 28, 2021 14:59
-
-
Save lummie/0475b4604a7c40cf68f897791112b8cd to your computer and use it in GitHub Desktop.
Go channel based Simple Worker pattern
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package main | |
import ( | |
"fmt" | |
"log" | |
"sync" | |
) | |
/* | |
This is an example of a worker pattern for channels | |
*/ | |
type WorkItem struct { | |
Num int | |
} | |
type WorkManager struct { | |
workToDo chan WorkItem | |
wgWork sync.WaitGroup // waitgroup for work items | |
} | |
func NewWorkManager(workBufferSize int) *WorkManager { | |
return &WorkManager{ | |
workToDo: make(chan WorkItem, workBufferSize), | |
wgWork: sync.WaitGroup{}, | |
} | |
} | |
func (w *WorkManager) Startup(workerCount int) { | |
for i := 0; i < workerCount; i++ { | |
go w.newWorker(i) | |
} | |
} | |
// newWorker is the implementation of the the work you need to do | |
// get some work to do of the channel and process it, then mark the work wg done | |
func (w *WorkManager) newWorker(id int) { | |
log.Printf("Worker %d started", id) | |
for workItem := range w.workToDo { | |
log.Printf("%v\n", workItem) | |
w.wgWork.Done() // mark work item as done | |
} | |
log.Printf("Worker %d finished", id) | |
} | |
func (w *WorkManager) AddWork(work WorkItem) { | |
w.wgWork.Add(1) | |
w.workToDo <- work // this will block if the channel becomes full as the workers are not working fast enough | |
} | |
func (w *WorkManager) WaitForWorkComplete() { | |
fmt.Println("Waiting for work to complete") | |
w.wgWork.Wait() // wait for any work to complete | |
fmt.Println("Work is complete") | |
} | |
func (w *WorkManager) Shutdown() { | |
w.WaitForWorkComplete() | |
close(w.workToDo) // close the work channel, this will cause each worker go routine to quit out the range exit nicely | |
} | |
func main() { | |
wm := NewWorkManager(100) | |
wm.Startup(10) | |
log.Println("create work items block 1") | |
for i := 0; i < 10; i++ { | |
wm.AddWork(WorkItem{Num: i}) | |
} | |
wm.WaitForWorkComplete() | |
log.Println("create work items block 2") | |
for i := 0; i < 10; i++ { | |
wm.AddWork(WorkItem{Num: 1000 + i}) | |
} | |
wm.Shutdown() | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment