forked from pibigstar/go-demo
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgoroutine.go
134 lines (125 loc) · 2.74 KB
/
goroutine.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
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
package goroutinue
import (
"context"
"errors"
"fmt"
"sync"
"time"
)
// 超时检测机制
func GetWithTimeout(d time.Duration) (string, error) {
ret := make(chan string)
go func() {
//do something
time.Sleep(d)
ret <- "Hello"
}()
select {
case result := <-ret:
return result, nil
case <-time.After(time.Millisecond * 100):
return "", errors.New("time out")
}
}
// 当我们启动多个任务时,如果有一个任务完成之后即可返回
// 例如:我们通过关键字去百度和谷歌搜索
// 当其中任意一个先拿到结果之后,我们就直接返回那一个
func GetOne() string {
ret := make(chan string)
for i := 0; i < 10; i++ {
go func(i int) {
ret <- fmt.Sprintf("%d : I get the result", i)
}(i)
}
//当ret中一有结果,就直接返回了
return <-ret
}
// 当所有任务执行完成之后,才将结果返回
func GetAll() string {
ret := make(chan string, 10)
for i := 0; i < 10; i++ {
go func(i int) {
ret <- fmt.Sprintf("%d : I get the result \n", i)
}(i)
}
// 当所有结果拿到之后,组装结果,返回
result := ""
for i := 0; i < 10; i++ {
result += <-ret
}
return result
}
// 使用watiGroup实现获取所有结果之后再返回
func GetAllWithGroup() string {
ret := make(chan string, 10)
var wg sync.WaitGroup
for i := 0; i < 10; i++ {
wg.Add(1)
go func(i int) {
ret <- fmt.Sprintf("%d : I get the result \n", i)
wg.Done()
}(i)
}
wg.Wait()
result := ""
for i := 0; i < 10; i++ {
result += <-ret
}
return result
}
// 取消任务
func CancelTask() {
//取消任务标识通道
cancel := make(chan struct{})
for i := 0; i < 5; i++ {
go func(i int, cancel chan struct{}) {
for {
if isCancel(cancel) {
break
}
time.Sleep(time.Millisecond * 5)
}
fmt.Println(i, ":Canceled")
}(i, cancel)
}
//当关闭通道,那么所有的goroutine都可以监听到
//如果仅仅是往这个通道发信息,那么只会有一个goroutine被取消
close(cancel)
time.Sleep(time.Millisecond * 20)
}
// 判断通道是否取消
func isCancel(cancel chan struct{}) bool {
select {
case <-cancel:
return true
default:
return false
}
}
// 使用上下文取消全部任务(一般这些任务分上下级的)
// 一个goroutine中又启动了其他的goroutine
func CancelAllTask() {
ctx, cancelFunc := context.WithCancel(context.Background())
for i := 0; i < 5; i++ {
go func(i int, ctx context.Context) {
for {
if isCancelFunc(ctx) {
break
}
time.Sleep(time.Millisecond * 5)
}
fmt.Println(i, ":Canceled")
}(i, ctx)
}
//取消全部任务
cancelFunc()
time.Sleep(time.Millisecond * 20)
}
func isCancelFunc(ctx context.Context) bool {
select {
case <-ctx.Done():
return true
default:
return false
}
}