goroutine

goroutine是Golang实现并发的一种手段,在一个Golang程序中,每一个goroutine相当于一个独立的执行单元,这类似于线程,但是并不是线程,而是Golang在语言层面上对线程的一种抽象。

Golang程序执行的时候默认会创建一个goroutine,可以叫他main goroutine。其他的goroutine需要我们通过go func()的形式创建。

这有点类似于一个工厂,工厂里面至少要有一个人员吧,我们称之为老板(main goroutine),当工厂只有老板一个人时,工厂还是可以正常运转的,所有的事情都需要老板亲历亲为呗。当我们在程序中又创建了一个goroutine时,就相当于招聘了一个员工,这样就可以把一些工作分给员工去做。

示例

这次我们来做一个简单的游戏吧。

假设我们的游戏里面有一个一维的地图,emmm其实就是一条线,这个地图上有个NPC或者敌人在全地图游荡。

 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
package main

import (
	"fmt"
	"time"
)

//地图宽度
const mapW = 10

//当前位置
var curPos = 0

//当前方向
var dir int = 1

func main() {
	go wander()
	display()
}

func display() {
	for {
		//退回到行首
		fmt.Print("\r")
		for x := 0; x < mapW; x++ {
			if x == curPos {
				//输出NPC
				fmt.Print("o")
			} else {
				//输出空白
				fmt.Print(" ")
			}
		}
		time.Sleep(100 * time.Microsecond)
	}
}

func wander() {
	for {
		nextPos := curPos + dir
		if nextPos < 0 || nextPos >= mapW {
			//达到地图边缘,切换方向
			dir = -dir
		} else {
			curPos = nextPos
			time.Sleep(time.Second)
		}
	}
}

在这个简单的游戏(甚至算不上游戏因为没有交互)中,程序使用了两个goroutine,一个是main goroutine(老板),负责渲染图像,即display方法,另外又通过go wander()创建了一个新的goroutine,负责更新NPC的位置。那我们可不可以把display的工作也交给一个新的goroutine(新员工)呢,如果我们这么做的话,程序会马上结束,这是因为main gouroutine的工作已经完成了。在程序中,如果main goroutine结束了,那么所有的goroutine都会结束。这个例子告诉我们一个道理:如果一个公司里面老板不再干活了,那么这个公司就完了┑( ̄Д  ̄)┍。

BGM