Goroutines
Goroutines 可以看作是轻量级线程。创建一个 goroutine 非常简单,只需要把 go 关键字放在函数调用语句前。为了说明这有多么简单,我们创建两个 finder 函数,并用 go 调用,让它们每次找到 "ore" 就打印出来。
func main() {
theMine := [5]string{"rock", "ore", "ore", "rock", "ore"}
go finder1(theMine)
go finder2(theMine)
}
程序输出结果如下:
Finder 1 found ore!
Finder 2 found ore!
Finder 1 found ore!
Finder 1 found ore!
Finder 2 found ore!
Finder 2 found ore!
可以看出,两个 finder 是并发运行的。哪一个先找到没有确定的顺序,当执行多次程序时,这个顺序并不总是相同的。
Channels
Channels 允许 go routines 之间相互通信。你可以把 channel 看作管道,goroutines 可以往里面发消息,也可以从中接收其它 go routines 的消息。
myFirstChannel := make(chan string)
Goroutines 可以往 channel 发送消息,也可以从中接收消息。这是通过箭头操作符 (<-) 完成的,它指示 channel 中的数据流向。
myFirstChannel <-"hello" // 发送
myVariable := <- myFirstChannel // 接收
现在通过 channel 我们可以让 gopher 一找到就立即传送给 gopher ,而不用等发现所有gopher。
func main() {
theMine := [5]string{"ore1", "ore2", "ore3"}
oreChan := make(chan string)
go func(mine [5]string) {
for _, item := range mine {
oreChan <- item //发送
}
}(theMine)
go func() {
for i := 0; i < 3; i++ {
foundOre := <-oreChan //接受
fmt.Println("Miner: Received " + foundOre + " from finder")
}
}()
<-time.After(time.Second * 5)
}
从下面的输出,可以看到 Miner 从 oreChan 读取了三次:
Miner: Received ore1 from finder
Miner: Received ore2 from finder
Miner: Received ore3 from finder
现在我们能在程序的 goroutines(gophers) 之间发送数据了。在开始用 channels 写复杂的程序之前,我们先来理解它的一些关键特性。