Go Engine Pattern
Hmm… I need to come back to this idea of a design pattern that resembles a plugable motor function.
package main
import (
"context"
"log"
"sync"
"time"
)
type AA func(context.Context, string, string, int) (int, error)
func Varoom(ctx context.Context, s0 string, sE string, t int) (int, error) {
gen := func(ctx context.Context) <-chan string {
dst := make(chan string)
var output string
go func() {
// Important to close dst
defer close(dst)
for {
output += s0 + "," + sE
select {
case <-ctx.Done():
log.Printf("ctx.Done() in Loop")
dst <- "done"
return // returning not to leak the goroutine
case dst <- output:
time.Sleep(time.Duration(t) * time.Second)
}
}
}()
return dst
}
for output := range gen(ctx) {
log.Printf("output: %s\n", output)
if ctx.Err() != nil {
log.Printf("calling break")
break
}
}
return 1, nil
}
type A struct {
sync.Mutex
S string
I int
D int
AA AA
}
func (a *A) PlugIn(aa AA) {
a.AA = aa
}
func (a *A) RunAA(s string) (int, error) {
a.Lock()
defer a.Unlock()
ctx, cancel := context.WithTimeout(context.Background(),
time.Duration(time.Duration(a.D)*time.Second))
defer cancel()
if a.AA == nil {
return -1, nil
}
return a.AA(ctx, a.S, s, a.I)
}
func main() {
a := A{}
a.S = "a"
a.I = 1
a.D = 5
a.PlugIn(Varoom)
a.RunAA("b")
}
Other examples..
package main
import (
"bytes"
"fmt"
"os"
)
func main() {
var stdoutBuff bytes.Buffer
defer stdoutBuff.WriteTo(os.Stdout)
intStream := make(chan int, 5)
go func() {
defer close(intStream)
defer fmt.Fprintln(&stdoutBuff, "Producer Done.")
for i := 0; i < 5; i++ {
fmt.Fprintf(&stdoutBuff, "Sending: %d\n", i)
intStream <- i
}
}()
for i := range intStream {
fmt.Fprintf(&stdoutBuff, "Received %v\n", i)
}
}