mirror of
https://github.com/crazybber/awesome-patterns.git
synced 2024-11-24 13:36:03 +03:00
test goroutine
This commit is contained in:
parent
f978e42036
commit
f7dd9679d3
@ -62,7 +62,7 @@ A curated collection of idiomatic design & application patterns for Go language.
|
||||
| Pattern | Description | Status |
|
||||
|:-------:|:----------- |:------:|
|
||||
| [N-Barrier](/concurrency/barrier.md) | Prevents a process from proceeding until all N processes reach to the barrier | ✘ |
|
||||
| [Bounded Parallelism](/concurrency/bounded_parallelism.md) | Completes large number of independent tasks with resource limits | ✔ |
|
||||
| [Bounded Parallelism](/concurrency/bounded/bounded_parallelism.md) | Completes large number of independent tasks with resource limits | ✔ |
|
||||
| [Broadcast](/concurrency/broadcast.md) | Transfers a message to all recipients simultaneously | ✘ |
|
||||
| [Coroutines](/concurrency/coroutine.md) | Subroutines that allow suspending and resuming execution at certain locations | ✘ |
|
||||
| [Generators](/concurrency/generator.md) | Yields a sequence of values one at a time | ✔ |
|
||||
|
@ -33,7 +33,7 @@
|
||||
* [Semaphore](/synchronization/semaphore.md)
|
||||
* [Concurrency Patterns](/README.md#concurrency-patterns)
|
||||
* [N-Barrier](/concurrency/barrier.md)
|
||||
* [Bounded Parallelism](/concurrency/bounded_parallelism.md)
|
||||
* [Bounded Parallelism](/concurrency/bounded/bounded_parallelism.md)
|
||||
* [Broadcast](/concurrency/broadcast.md)
|
||||
* [Coroutines](/concurrency/coroutine.md)
|
||||
* [Generators](/concurrency/generator.md)
|
||||
|
@ -40,11 +40,11 @@ type (
|
||||
)
|
||||
|
||||
type (
|
||||
eventObserver struct{
|
||||
eventObserver struct {
|
||||
id int
|
||||
}
|
||||
|
||||
eventNotifier struct{
|
||||
eventNotifier struct {
|
||||
// Using a map with an empty struct allows us to keep the observers
|
||||
// unique while still keeping memory usage relatively low.
|
||||
observers map[Observer]struct{}
|
||||
@ -84,10 +84,10 @@ func main() {
|
||||
tick := time.NewTicker(time.Second).C
|
||||
for {
|
||||
select {
|
||||
case <- stop:
|
||||
case <-stop:
|
||||
return
|
||||
case t := <-tick:
|
||||
n.Notify(Event{Data: t.UnixNano()})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Bounded Parallelism Pattern
|
||||
|
||||
[Bounded parallelism](https://blog.golang.org/pipelines#TOC_9.) is similar to [parallelism](parallelism.md), but allows limits to be placed on allocation.
|
||||
[Bounded parallelism](https://blog.golang.org/pipelines#TOC_9.) is similar to [parallelism](../parallelism.md), but allows limits to be placed on allocation.
|
||||
|
||||
# Implementation and Example
|
||||
|
24
playground/goroutine/basic_chan_test.go
Normal file
24
playground/goroutine/basic_chan_test.go
Normal file
@ -0,0 +1,24 @@
|
||||
package goroutine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestFiveGopherWithChan(t *testing.T) {
|
||||
c := make(chan int)
|
||||
for i := 0; i < 5; i++ {
|
||||
go sleepyGopherWithChan(i, c)
|
||||
}
|
||||
for i := 0; i < 5; i++ {
|
||||
gopherID := <-c
|
||||
fmt.Println("gopher ", gopherID, " has finished sleeping")
|
||||
}
|
||||
}
|
||||
|
||||
func sleepyGopherWithChan(id int, c chan int) {
|
||||
time.Sleep(2 * time.Second)
|
||||
fmt.Println("... ", id, " snore ...")
|
||||
c <- id
|
||||
}
|
25
playground/goroutine/basic_test.go
Normal file
25
playground/goroutine/basic_test.go
Normal file
@ -0,0 +1,25 @@
|
||||
package goroutine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestOneGopher(t *testing.T) {
|
||||
go sleepyGopher(1)
|
||||
time.Sleep(3 * time.Second)
|
||||
}
|
||||
|
||||
func TestFiveGopher(t *testing.T) {
|
||||
c := make(chan int)
|
||||
for i := 0; i < 5; i++ {
|
||||
go sleepyGopherWithChan(i, c)
|
||||
}
|
||||
time.Sleep(3 * time.Second)
|
||||
}
|
||||
|
||||
func sleepyGopher(id int) {
|
||||
time.Sleep(2 * time.Second)
|
||||
fmt.Println("... ", id, " snore ...")
|
||||
}
|
32
playground/goroutine/basic_waitgroup_test.go
Normal file
32
playground/goroutine/basic_waitgroup_test.go
Normal file
@ -0,0 +1,32 @@
|
||||
package goroutine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"sync"
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestWaitGophers(t *testing.T) {
|
||||
var gophers = []string{"tom", "peter", "john", "brown"}
|
||||
|
||||
var waitGroup sync.WaitGroup
|
||||
waitGroup.Add(len(gophers))
|
||||
|
||||
for i := 0; i < len(gophers); i++ {
|
||||
go func(wg *sync.WaitGroup, name string) {
|
||||
sleepyGopherSnore(name)
|
||||
wg.Done()
|
||||
}(&waitGroup, gophers[i])
|
||||
}
|
||||
|
||||
waitGroup.Wait()
|
||||
|
||||
fmt.Println("All done")
|
||||
}
|
||||
|
||||
func sleepyGopherSnore(name string) {
|
||||
fmt.Println(name, ": ... start snore")
|
||||
time.Sleep(2 * time.Second)
|
||||
fmt.Println(name, ": ... snore")
|
||||
}
|
11
playground/goroutine/deadlock_test.go
Normal file
11
playground/goroutine/deadlock_test.go
Normal file
@ -0,0 +1,11 @@
|
||||
package goroutine
|
||||
|
||||
import "testing"
|
||||
|
||||
// A deadlock happens when a group of goroutines are waiting for each other and none of them is able to proceed.
|
||||
// The program will get stuck on the channel send operation waiting forever for someone to read the value.
|
||||
// Go is able to detect situations like this at runtime.
|
||||
func TestDeadlock(t *testing.T) {
|
||||
c := make(chan int)
|
||||
<-c
|
||||
}
|
39
playground/goroutine/pipeline_test.go
Normal file
39
playground/goroutine/pipeline_test.go
Normal file
@ -0,0 +1,39 @@
|
||||
package goroutine
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func sourceGopher(downstream chan string) {
|
||||
for _, v := range []string{"hello world", "a bad apple", "goodbye all"} {
|
||||
downstream <- v
|
||||
}
|
||||
close(downstream)
|
||||
}
|
||||
|
||||
func filterGopher(upstream, downstream chan string) {
|
||||
for item := range upstream {
|
||||
fmt.Println("filter ", item)
|
||||
|
||||
if !strings.Contains(item, "bad") {
|
||||
downstream <- item
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func printGopher(upstream chan string) {
|
||||
for item := range upstream {
|
||||
fmt.Println("print ", item)
|
||||
}
|
||||
}
|
||||
|
||||
// Pipeline source->filter->print
|
||||
func TestPipeline(t *testing.T) {
|
||||
c0 := make(chan string)
|
||||
c1 := make(chan string)
|
||||
go sourceGopher(c0)
|
||||
go filterGopher(c0, c1)
|
||||
printGopher(c1)
|
||||
}
|
Loading…
Reference in New Issue
Block a user