Skip to content
This repository was archived by the owner on Mar 5, 2026. It is now read-only.

Commit c006018

Browse files
committed
change return from a task to []any
1 parent f00801f commit c006018

File tree

6 files changed

+105
-23
lines changed

6 files changed

+105
-23
lines changed

README.md

Lines changed: 21 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ import "github.com/manhvu/easyworker"
5656

5757
## Use Cases
5858

59-
### Supervisor
59+
### Supervisor model
6060

6161
This is used for generic worker(child).
6262
Every children has a owner restart strategy.
@@ -71,6 +71,9 @@ Children will be started after they are added to supervisor.
7171

7272
In restart case, children will re-use last parameters (if task don't change it) of task.
7373

74+
Child, doesn't return any value from task.
75+
You need add code to get value from task if you needed.
76+
7477
Supervisor -> Child -> call user functions
7578

7679
Basic supervisor's flow:
@@ -178,6 +181,9 @@ Number of workers is number of goroutine will run tasks.
178181

179182
In retry case, worker will re-use last parameters of task.
180183

184+
Result of each task is a []any.
185+
You need to get true value from any(interface{}).
186+
181187
EasyTask example:
182188

183189
```go
@@ -230,6 +236,9 @@ Number of workers is number of goroutines used for processing streaming task.
230236

231237
In retry case, workers will re-use last parameters of task.
232238

239+
Result of each task is a []any.
240+
You need to get true value from any(interface{}).
241+
233242
EasyStream example:
234243

235244
```go
@@ -258,19 +267,19 @@ myStream.Run()
258267

259268
// receive data from stream.
260269
go func() {
261-
for {
262-
r := <-outCh
263-
fmt.Println("stream result: ", r)
264-
}
270+
for {
271+
r := <-outCh
272+
fmt.Println("stream result: ", r)
273+
}
265274
}()
266275

267276
// send data to stream.
268277
go func() {
269-
for i := 0; i < 15; i++ {
270-
input := []any{i, "hello"}
271-
inCh <- input
272-
fmt.Println("stream sent: ", input)
273-
}
278+
for i := 0; i < 15; i++ {
279+
input := []any{i, "hello"}
280+
inCh <- input
281+
fmt.Println("stream sent: ", input)
282+
}
274283
}()
275284

276285

@@ -290,6 +299,8 @@ Second param is channel that user can receive signal.
290299

291300
Signal is a struct with reference id and kind of end (failed, done).
292301

302+
Go doesn't support return value, you need an other way to get if you neened.
303+
293304
Example 1:
294305

295306
```go

caller.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import (
99
/*
1010
call user's function througth reflect.
1111
*/
12-
func invokeFun(fun any, args ...any) (ret reflect.Value, err error) {
12+
func invokeFun(fun any, args ...any) (ret []any, err error) {
1313
// catch if panic by user code.
1414
defer func() {
1515
if r := recover(); r != nil {
@@ -24,10 +24,10 @@ func invokeFun(fun any, args ...any) (ret reflect.Value, err error) {
2424
fnType := fn.Type()
2525
numIn := fnType.NumIn()
2626
if numIn > len(args) {
27-
return reflect.ValueOf(nil), fmt.Errorf("function must have minimum %d params. Have %d", numIn, len(args))
27+
return nil, fmt.Errorf("function must have minimum %d params. Have %d", numIn, len(args))
2828
}
2929
if numIn != len(args) && !fnType.IsVariadic() {
30-
return reflect.ValueOf(nil), fmt.Errorf("func must have %d params. Have %d", numIn, len(args))
30+
return nil, fmt.Errorf("func must have %d params. Have %d", numIn, len(args))
3131
}
3232
params := make([]reflect.Value, len(args))
3333
for i := 0; i < len(args); i++ {
@@ -39,24 +39,26 @@ func invokeFun(fun any, args ...any) (ret reflect.Value, err error) {
3939
}
4040
argValue := reflect.ValueOf(args[i])
4141
if !argValue.IsValid() {
42-
return reflect.ValueOf(nil), fmt.Errorf("func Param[%d] must be %s. Have %s", i, inType, argValue.String())
42+
return nil, fmt.Errorf("func Param[%d] must be %s. Have %s", i, inType, argValue.String())
4343
}
4444
argType := argValue.Type()
4545
if argType.ConvertibleTo(inType) {
4646
params[i] = argValue.Convert(inType)
4747
} else {
48-
return reflect.ValueOf(nil), fmt.Errorf("method Param[%d] must be %s. Have %s", i, inType, argType)
48+
return nil, fmt.Errorf("method Param[%d] must be %s. Have %s", i, inType, argType)
4949
}
5050
}
5151

5252
result := fn.Call(params)
5353

54-
//log.Println("invoke result:", result)
54+
ret = make([]any, len(result))
5555

56-
if len(result) > 0 {
57-
ret = result[0]
56+
for i, r := range result {
57+
ret[i] = r.Interface()
5858
}
5959

60+
//log.Println("invoke result:", result)
61+
6062
return ret, nil
6163
}
6264

caller_test.go

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
package easyworker
2+
3+
import (
4+
"errors"
5+
"log"
6+
"testing"
7+
)
8+
9+
func simpleLoopReturn(a int) int {
10+
ret := 0
11+
for i := 0; i < a; i++ {
12+
ret += i
13+
}
14+
15+
return ret
16+
}
17+
18+
func returnMultiValue() (i int, f float64, b bool, e error) {
19+
i = 123
20+
f = 1.2
21+
b = true
22+
e = errors.New("test return")
23+
return
24+
}
25+
26+
func TestInvokeNoArg(t *testing.T) {
27+
result, err := invokeFun(simpleLoopNoArg)
28+
29+
if err != nil {
30+
t.Error("test invoke with no argument failed, ", err)
31+
} else {
32+
log.Println("result: ", result)
33+
}
34+
}
35+
36+
func TestInvokePanic(t *testing.T) {
37+
_, err := invokeFun(simpleLoopWithPanic, 5)
38+
39+
if err == nil {
40+
t.Error("expected error but no return error.")
41+
} else {
42+
log.Println("expected is ok, err: ", err)
43+
}
44+
}
45+
46+
func TestInvokeReturn(t *testing.T) {
47+
result, err := invokeFun(simpleLoopReturn, 5)
48+
49+
if err != nil {
50+
t.Error("test invoke with no argument failed, ", err)
51+
} else {
52+
log.Println("result: ", result)
53+
if result[0] != 10 {
54+
t.Error("return incorrect value")
55+
}
56+
}
57+
}
58+
59+
func TestInvokeReturnMultiValue(t *testing.T) {
60+
result, err := invokeFun(returnMultiValue)
61+
62+
if err != nil {
63+
t.Error("test invoke with no argument failed, ", err)
64+
} else {
65+
log.Println("result: ", result)
66+
}
67+
}

gomonitor.go

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,13 +19,14 @@ const (
1919
type GoSignal struct {
2020
// Monitor reference id.
2121
RefId int64
22+
2223
// Kind of signal (SIGNAL_DONE, SIGNAL_FAILED)
2324
Signal int
2425
}
2526

2627
type monitorChan chan GoSignal
2728

28-
// A goroutine can be monitored.
29+
// A struct wrap goroutine to handle panic and can re-run easily.
2930
type Go struct {
3031
lock sync.Mutex
3132

@@ -46,7 +47,9 @@ func getNewRefId() int64 {
4647
}
4748

4849
/*
49-
Create new Go.
50+
Create new Go struct.
51+
The first parameter is user function.
52+
The second parameter and more is parameter for parameter of user function.
5053
*/
5154
func NewGo(fun any, params ...any) (ret *Go, retErr error) {
5255
if retErr = verifyFunc(fun); retErr != nil {
@@ -65,6 +68,7 @@ func NewGo(fun any, params ...any) (ret *Go, retErr error) {
6568

6669
/*
6770
Create Go and run.
71+
Same with function NewGo but run after create Go struct.
6872
*/
6973
func NewGoAndRun(fun any, params ...any) (ret *Go, retErr error) {
7074
ret, retErr = NewGo(fun, params...)

supervisor_test.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ func simpleLoopNoArg() {
1818
for i := 0; i < 50; i++ {
1919
time.Sleep(time.Millisecond)
2020
}
21-
2221
}
2322

2423
func loopRun(a int, testSupporter chan int) {

worker.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package easyworker
22

33
import (
44
"log"
5-
"reflect"
65
"time"
76
)
87

@@ -65,7 +64,7 @@ func (w *worker) run() {
6564

6665
var (
6766
task msg
68-
ret reflect.Value
67+
ret []any
6968
err error
7069
)
7170

0 commit comments

Comments
 (0)