在前面的例子中,我們已經探討了Concurrent Programming
的一些案例.
Golang是屬於使用訊息交換的方式,來處理processes之間交換資料的需求.
也就是前面介紹過的channel.
今天來看看整合起來的範例.讓油達大師與玉面飛鷹打一下模擬的交戰.
程式大致上就是由Main()先建立一個channel,傳給兩個goroutine,
當作攻擊的計數器,兩個goroutine都從Main()接收了一個badluck的數字,
每次都會自己產生一個小於20亂數整數,當亂數與badluck相等時,就失敗,
會關閉channel,自己脫離;所以只要判斷channel是否被關閉,就知道對方是否出包,
然後宣佈自己獲勝,脫離.
我們也在goroutine應用了defer來通知workgroup,當兩個goroutine都脫離時,
Main()就能正常關閉.
// hello76
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
var wg sync.WaitGroup
func init() {
rand.Seed(time.Now().UnixNano())
}
func main() {
hitcount := make(chan int)
wg.Add(2)
go 油達大師(hitcount, 13)
go 玉面飛鷹(hitcount, 7)
hitcount <- 1
wg.Wait()
}
func 油達大師(hitcount chan int, badluck int) {
name := "油達大師"
defer wg.Done()
for {
mycount, ok := <-hitcount
if !ok {
fmt.Printf("%s贏了!!\n", name)
return
}
n := rand.Intn(20)
if n%badluck == 0 {
fmt.Printf("%s內力耗盡!\n", name)
close(hitcount)
return
}
fmt.Printf("%s出了第%d招!\n", name, mycount)
mycount++
hitcount <- mycount
}
}
func 玉面飛鷹(hitcount chan int, badluck int) {
name := "玉面飛鷹"
defer wg.Done()
for {
mycount, ok := <-hitcount
if !ok {
fmt.Printf("%s贏了!!\n", name)
return
}
n := rand.Intn(20)
if n%badluck == 0 {
fmt.Printf("%s羽毛脫落!\n", name)
close(hitcount)
return
}
fmt.Printf("%s出了第%d招!\n", name, mycount)
mycount++
hitcount <- mycount
}
}
執行過程:
因為是用亂數,每次都會不同.執行兩次看看.
./hello76
油達大師出了第1招!
玉面飛鷹出了第2招!
油達大師出了第3招!
玉面飛鷹出了第4招!
油達大師出了第5招!
玉面飛鷹出了第6招!
油達大師內力耗盡!
玉面飛鷹贏了!!
./hello76
油達大師出了第1招!
玉面飛鷹出了第2招!
油達大師出了第3招!
玉面飛鷹出了第4招!
油達大師出了第5招!
玉面飛鷹羽毛脫落!
油達大師贏了!!