https://github.com/jcbritobr/go-concurrency-patterns
Examples on how to implement concurrency patterns in golang, and use the best feature of the language.
https://github.com/jcbritobr/go-concurrency-patterns
concurrent-programming golang parallel-programming parallelism patterns
Last synced: 10 months ago
JSON representation
Examples on how to implement concurrency patterns in golang, and use the best feature of the language.
- Host: GitHub
- URL: https://github.com/jcbritobr/go-concurrency-patterns
- Owner: jcbritobr
- License: mit
- Created: 2020-07-23T11:56:45.000Z (almost 6 years ago)
- Default Branch: master
- Last Pushed: 2023-04-26T13:39:06.000Z (about 3 years ago)
- Last Synced: 2025-06-22T11:02:44.742Z (12 months ago)
- Topics: concurrent-programming, golang, parallel-programming, parallelism, patterns
- Language: Go
- Homepage:
- Size: 84 KB
- Stars: 2
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
## Golang Concurrency Patterns Examples
This repository contains implemented golang concurrency patterns.
* Generator/Iterator \
Generator pattern is a way to a generate data sequences using paralelism. Using this pattern we are able to make the consumer run in parallel with the generator.
**Implementation**
```go
func generator(buffer ...int) <-chan int {
// a channel that will be returned with data
c := make(chan int)
// parallel process
go func() {
// iterate over incomming data chunk
for item := range buffer {
// pass data for channel
c <- item
}
// when finnished, close the channel
close(c)
}()
//return the channel
return c
}
```
**Use**
```go
// data chunk
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 0}
// load data into channel
g := generator(data...)
// consum the channel
for i := range g {
// print result data chunk
fmt.Println("item:", i)
}
```
* Future \
A Future will start a parallel computation, and its results will be available in the future. In golang, a simple goroutine can be use to implement this funcionality, without use of third party libraries or standard ones.
**Implementation**
```go
func fiboFuture(number int) <-chan int {
// Channel with the result
c := make(chan int)
// Starts a parallel process to calc fibonacci number
go func() {
if number <= 1 {
c <- number
return
}
fib := 1
prevFib := 1
for i := 0; i < number; i++ {
temp := fib
fib += prevFib
prevFib = temp
}
// Send the result to channel
c <- fib
// Close channel
close(c)
}()
return c
}
```
**Use**
```go
// Gets a future processing
future := fiboFuture(44)
// Prints the result of future. If still processing, instead, future will block
fmt.Println("result of future processing:", <-future)
```
* Fan-in/Fan-out \
The best way to implement a processing pipeline in golang is using the fan in/out pattern. The pattern is built by a function and a goroutine
that transports and loads data, using channels, to another. In the end of process, all the goroutines data are merged into one. Its a way of multiplexing and demultiplexing multiple input data.
See image below:
**Implementation**
**Use**
```go
// data to be processed
data := []int{1, 2, 3, 4, 5}
// generator loads data
g := generator(data...)
// fan-out the data in square pipeline
sq1 := sq(g)
sq2 := sq(g)
// consumn the parallel square pipeline - fan-in
for item := range merge(sq1, sq2) {
fmt.Println(item)
}
```
* WorkersPool \
WorkersPool is a pattern that aims to control the number of goroutines available to a system or application. If we create a pool with 3 workers, than no more goroutines can be spawned to new tasks, and its tasks will be waiting to others finnish.
**Implementation**
```go
type ExecFunc func()
type ThreadPool struct {
receiver chan ExecFunc
size int
}
func NewThreadPool(size int) *ThreadPool {
pool := &ThreadPool{
receiver: make(chan ExecFunc),
size: size,
}
return pool
}
func (t ThreadPool) start() {
for i := 0; i < t.size; i++ {
go func() {
for {
f := <-t.receiver
f()
}
}()
}
}
func (t *ThreadPool) Execute(f ExecFunc) {
t.receiver <- f
}
```
**Use**
```go
pool := NewThreadPool(3)
var wg sync.WaitGroup
wg.Add(2)
pool.start()
job := func(id int) {
for i := 0; i < 1000; i++ {
println(id, "->", i)
}
}
pool.Execute(func() {
job(1)
wg.Done()
})
pool.Execute(func() {
job(2)
wg.Done()
})
wg.Wait()
```