/
exp_goroutine_api_sync.go
118 lines (97 loc) · 3.01 KB
/
exp_goroutine_api_sync.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
package main
import (
"fmt"
"github.com/pkg/errors"
"time"
)
/*
* 外部同步接口处理
* 业务场景:外部接口耗时,需要转为异步处理结果
*/
type SyncApiData string
type SyncApiError error
type DecoratorSyncApiResult struct {
ApiData SyncApiData
ApiError SyncApiError
}
// 模拟外部请求(正常场景)
func doSyncApiSuccess() (SyncApiData, SyncApiError) {
//time.Sleep(time.Second)
return "api data", nil
}
// 模拟外部请求(异常场景)
func doSyncApiFailure() (SyncApiData, SyncApiError) {
time.Sleep(time.Second)
return "", errors.New("api failure")
}
// 模拟外部请求(超时场景)
func doSyncApiTimeout() (SyncApiData, SyncApiError) {
time.Sleep(10 * time.Second)
return "", errors.New("api timeout")
}
// 接口异步请求装饰器
func syncApiRequestDecorator(apiFunc func() (SyncApiData, SyncApiError), decoratorResultChan chan DecoratorSyncApiResult, timeout int) {
d := time.Duration(timeout) * time.Second
timeAfter := time.After(d)
fmt.Println("[request ] start")
done := make(chan bool) // 外部接口请求完成
go func(decoratorResultChan chan DecoratorSyncApiResult) {
res, err := apiFunc()
decoratorResultChan <- DecoratorSyncApiResult{res, err}
done <- true
}(decoratorResultChan)
fmt.Println("[request ] end")
select {
case <-done:
fmt.Println("[request ] get response!")
return
case <-timeAfter:
fmt.Println("[request ] timeout...")
decoratorResultChan <- DecoratorSyncApiResult{"", errors.New("timeout")}
return
}
}
// 接口异步结果处理器
func syncApiResultHandler(decoratorResultChan chan DecoratorSyncApiResult, done chan bool) {
for {
select {
case decoratorResult := <-decoratorResultChan:
fmt.Println("[response]", "data:", decoratorResult.ApiData, "; error:", decoratorResult.ApiError)
done <- true
return
default:
fmt.Println("[response] no message received")
time.Sleep(time.Second)
}
}
}
func main() {
// 一、普通方式(阻塞)
//_, e := doSyncApiFailure()
//if e != nil{
// fmt.Println(e.Error())
//}
timeoutRequest := 5
resultChan := make(chan DecoratorSyncApiResult, 1)
// 二、同步协程方式(阻塞)
//go func(decoratorSyncApiResultChan chan DecoratorSyncApiResult) {
// res, err := doSyncApiFailure()
// decoratorSyncApiResultChan <- DecoratorSyncApiResult{res, err}
// close(decoratorSyncApiResultChan)
//}(resultChan)
//
//apiResult := <-resultChan
//if apiResult.ApiError != nil {
// fmt.Println(apiResult.ApiError)
//}
// 三、异步协程方式(非阻塞)
forever := make(chan bool)
// 外部请求 - 异步方式发起(三种场景:正常、失败、超时)
//go syncApiRequestDecorator(doSyncApiSuccess, resultChan, timeoutRequest)
go syncApiRequestDecorator(doSyncApiFailure, resultChan, timeoutRequest)
//go syncApiRequestDecorator(doSyncApiTimeout, resultChan, timeoutRequest)
// 外部请求 - 异步处理结果
go syncApiResultHandler(resultChan, forever)
fmt.Printf("[*] Waiting for logs. To exit press CTRL+C\n")
<-forever
}