wait
[
{
"method": "controller:method1",
"params": {},
"id": 1
},
{
"method": "controller:method2",
"params": {},
"id": 2,
"wait": 1
}
]
package main
import (
"fmt"
"sync"
"time"
)
type chain struct {
Req *req
Wait chan bool
Signal chan bool
IsWaiting bool
}
type req struct {
Method func()
ID int
W int
}
func main() {
chainigs := make(map[int]*chain)
var fncs []*req
r1 := &req{
Method: func1,
ID: 1,
W: 0,
}
r2 := &req{
Method: func2,
ID: 2,
W: 1,
}
r3 := &req{
Method: func3,
ID: 3,
W: 0,
}
fncs = append(fncs, r1, r2, r3)
for _, req := range fncs {
ch := &chain{}
ch.Req = req
signalChan := make(chan bool)
ch.Signal = signalChan
chainigs[req.ID] = ch
if waitChan, ok := chainigs[req.W]; ok {
ch.Wait = waitChan.Signal
ch.IsWaiting = true
} else {
ch.IsWaiting = false
}
chainigs[req.ID] = ch
}
var wg sync.WaitGroup
for _, schain := range chainigs {
wg.Add(1)
go func(c *chain) {
if c.IsWaiting {
select {
case <-c.Wait:
c.Req.Method()
wg.Done()
go func() {
c.Signal <- true
close(c.Signal)
}()
}
} else {
c.Req.Method()
wg.Done()
c.Signal <- true
}
}(schain)
}
wg.Wait()
}
func func1() {
time.Sleep(2 * time.Second)
fmt.Println("FORM 1")
}
func func2() {
fmt.Println("FROM 2")
}
func func3() {
time.Sleep(2 * time.Second)
fmt.Println("FROM 3")
}
chain
имеет два поля с каналами Wait
и Signal
. Wait
- сдержит канал Signal
другой структуры, выполение которой нужно ожидать. Ну а дальше запуск в цикле гороутин, и проверяем, если chain должен ожидать выполнение другого, то ждем сигнала. Если нет, то просто выполняем функцию и посылаем завершающий сигнал. При такой реализации удается строить цепочки вызовов, и в целом программа работает правильно. Меня интересует насколько правильным можно считать такой подход? Возможно, есть паттерны намного лучше и красивей для реализации такой возможности? [
{
"method": "controller:method1",
"params": {},
"id": 1
},
{
"method": "controller:method2",
"params": {},
"id": 2,
"wait": 1
},
{
"method": "controller:method2",
"params": {},
"id": 3,
"wait": 1
},
{
"method": "controller:method2",
"params": {},
"id": 4,
"wait": 2
}
{
"method": "controller:method2",
"params": {},
"id": 5
}
]
[
[
{
"method": "controller:method1",
"params": {},
"id": 1
},
{
"method": "controller:method2",
"params": {},
"id": 5
}
],
[
{
"method": "controller:method2",
"params": {},
"id": 2,
"wait": 1
},
{
"method": "controller:method2",
"params": {},
"id": 3,
"wait": 1
},
],
[
{
"method": "controller:method2",
"params": {},
"id": 4,
"wait": 2
}
]
]
for _, step := range steps {
for _, f : range step {
f.method(f.params)
}
}