Skip to content

consider using orDone channel pattern #262

@plastikfan

Description

@plastikfan

found on youtube learn the Go concurrency pattern that blew my mind (by Kantan Coding) (Not sure if this is applicable to anything in lorax, I just wanted somewhere to record the act that I saw this useful concurrency design pattern)

Allows the done/select channel pattern to be extracted out into another function that handles done notification using a separate go routine and a relay stream. Clients now do not need to implement the select/done channel, they instead range over the relay stream that is returned from the newly defined function orDone.

Here is the example code:

func main() {
	var wg sync.WaitGroup

	cows := make(chan interface{}, 10)
	done := make(chan interface{}, 10)

	wg.Add(1)
	go consumeCows(&wg, done, cows)
}

func consumeCows(wg *sync.WaitGroup, done, cows <-chan interface{}) {
	defer wg.Done()

	for cow := range orDone(done, cows) {
		fmt.Printf("%v\n", cow)
	}
}

func orDone(done, c <-chan interface{}) <-chan interface{} {
	relayCh := make(chan interface{})

	go func() {
		defer close(relayCh)

		for {
			select {
			case <-done:
				return
			case v, ok := <-c:
				if !ok {
					return
				}
				select {
				case relayCh <- v:
				case <-done:
					return
				}
			}
		}
	}()

	return relayCh
}

Also see: Go Concurrency Patterns: Pipelines and cancellation by Sameer Ajmani (13-mar-2014)

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions