Go指南学习笔记十二

goroutine

goroutine是Go运行时环境管理的轻量级线程

go f(x,y,z)

开启一个新的goroutine执行。

f,x,y,z是在当前goroutine中定义的,但是在新的goroutine中运行f

goroutine在相同的地址空间中运行,因此访问共享内存必须同步。sync提供了这种可能,不过在Go中并不经常用到,因为还有其他办法。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package main
import (
"fmt"
"time"
)
func say(s string) {
for i:=0; i<5; i++ {
time.Sleep(100 * time.Millisecond)
fmt.Println(s)
}
}
func main() {
go say("world")
say("hello")
}

运行结果,helloworld交替运行。

1
2
3
4
5
6
7
8
9
10
11
[Running] go run "f:\study\go\smp\src\goroutine.go"
world
hello
hello
world
hello
world
hello
world
world
hello

channel

channel是有类型的管道,可以使用channel操作符<-对齐发送或者接受值

1
2
ch <- v //将v送给channel ch
v := <-ch //从ch接收,并且赋值给v

和map与slice一样,使用前必须创建

1
ch := make(chan int)

默认情况下,在另一端准备好之前,发送和接受都会阻塞。这使得goroutine可以在没有明确的锁或竞态变量的情况下进行同步。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
package main
import (
"fmt"
)
func sum(a []int, c chan int) {
sum := 0
for _, v := range a {
sum += v
}
c <- sum // 将sum送入c
}
func main() {
a := []int{7, 2, 8, -9, 4, 0}
c := make(chan int)
go sum(a[:len(a)/2], c)
go sum(a[len(a)/2:], c)
x, y := <-c, <-c
fmt.Println(x, y , x+y)
}

输出结果

1
-5 17 12 或者 17 -5 12

缓冲channel

channel是可以带缓冲的。为make提供第二个参数作为缓冲长度来初始化一个缓冲channel

1
ch := make(chan int, 100)

向带缓冲的channel发送数据时,只有在缓冲区慢的时候才会发生阻塞。而当缓冲区为空时接受操作会阻塞。

1
2
3
4
5
6
7
8
9
10
11
12
13
package main
import (
"fmt"
)
func main() {
ch := make(chan int, 2)
ch <- 1
ch <- 2
fmt.Println(<-ch)
fmt.Println(<-ch)
}

输出结果

1
2
1
2

如果您觉得对您有帮助,谢谢您的赞赏!