1、go语言中goroute之间通信有两种方式:
- 通过全局变量,这种方式得加锁
- 通过channel进行通信
下面是一个通过全局变量进行通信的例子:
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
|
package main
import (
"fmt"
"sync"
"time"
)
var (
m = make(map[int]uint64)
lock sync.Mutex
)
type task struct {
n int
}
func calc(t *task) {
var sum uint64
sum = 1
for i := 1; i < t.n; i++ {
sum *= uint64(i)
}
lock.Lock()
m[t.n] = sum
lock.Unlock()
}
func main() {
for i := 0; i < 20; i++ {
t := &task{n: i}
go calc(t)
}
time.Sleep(10 * time.Second)
lock.Lock()
for k, v := range m {
fmt.Printf("%d!=%v\n", k, v)
}
lock.Unlock()
}
|
输出结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
0!=1
7!=720
11!=3628800
5!=24
14!=6227020800
16!=1307674368000
18!=355687428096000
13!=479001600
19!=6402373705728000
1!=1
9!=40320
10!=362880
4!=6
2!=1
3!=2
12!=39916800
8!=5040
6!=120
15!=87178291200
17!=20922789888000</pre>
|
2、理解go中的并发
a、可以看到通过关键字go,运行的时候不是串行执行的,使用go,起了多个goroute。由于map是无序的,排除map的没有顺序,修改如下,直接打印出来,看的可能更清楚一点;
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
|
package main
import (
"fmt"
"sync"
)
var (
m = make(map[int]uint64)
lock sync.Mutex
)
type task struct {
n int
}
func calc(t *task) {
var sum uint64
sum = 1
for i := 1; i < t.n; i++ {
sum *= uint64(i)
}
fmt.Println(t.n, sum)
lock.Lock()
m[t.n] = sum
lock.Unlock()
}
func main() {
for i := 0; i < 20; i++ {
t := &task{n: i}
go calc(t)
}
// time.Sleep(10 * time.Second)
// lock.Lock()
// for k, v := range m {
// fmt.Printf("%d!=%v\n", k, v)
// }
// lock.Unlock()
}
|
输出结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
1 1
3 2
2 1
4 6
5 24
13 479001600
7 720
6 120
15 87178291200
9 40320
10 362880
8 5040
14 6227020800
16 1307674368000
18 355687428096000
12 39916800
11 3628800
17 20922789888000
19 6402373705728000
0 1
|
b、如果go没有关键字,也就是没有启动多个goroute的话,应该只是在main函数的那个goroute里面串行执行的,去掉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
|
package main
import (
"fmt"
"sync"
"time"
)
var (
m = make(map[int]uint64)
lock sync.Mutex
)
type task struct {
n int
}
func calc(t *task) {
var sum uint64
sum = 1
for i := 1; i < t.n; i++ {
sum *= uint64(i)
}
fmt.Println(t.n, sum)
lock.Lock()
m[t.n] = sum
lock.Unlock()
}
func main() {
for i := 0; i < 20; i++ {
t := &task{n: i}
calc(t)
}
time.Sleep(10 * time.Second)
// lock.Lock()
// for k, v := range m {
// fmt.Printf("%d!=%v\n", k, v)
// }
// lock.Unlock()
}
|
没有go关键字,执行结果如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
0 1
1 1
2 1
3 2
4 6
5 24
6 120
7 720
8 5040
9 40320
10 362880
11 3628800
12 39916800
13 479001600
14 6227020800
15 87178291200
|
上面也可以看到,go的并发是通过go关键字来实现的,main函数本身会启动一个goroute,如果我们使用go关键字,是会启动新的goroute,它是和main函数的goroute并发进行的,但如果main函数的goroute结束了,整个程序就结束了,所以我们等待了10m。