程序運行后,雖然mian函數和ready函數中都print了開始執行的語句,但是很明顯,在Goroutine內的函數并沒有執行完成。所以我們為了更精準的控制Goroutine的并發,需要使用Channel進行控制。
基本概念
Goroutine是一個被Go運行時管理的輕量級線程(A goroutine is a lightweight thread managed by the Go runtime)。
為什么沒有采用現有的表示并發名詞來解釋Go語言中的并發呢?因為現有的線程、協程、進程等都無法準確表達Goroutine。
Goroutines使用方法
函數并發執行
與普通函數類似,我們調用Goroutines時只需要在函數前加上go關鍵字。下面的例子中go ready()就會并發執行。
package main
import (
"fmt"
"time"
)
func ready() {
fmt.Println("Run func in a goroutine")
}
func main() {
go ready()
time.Sleep(time.Second * 3)
fmt.Println("Main function done")
}
匿名并發函數
如果你不想單獨定義,則可以使用匿名方式
package main
import (
"fmt"
"time"
)
func main() {
go func() {
fmt.Println("Run anonymous func in goroutine.")
}()
time.Sleep(time.Second * 3)
fmt.Println("Main function done")
}
如何控制并發
上面的示例中,我們在主函數刻意的等待了3秒,如果沒有這3秒會發生什么呢?我們將time.Sleep注釋掉,另外由于time模塊沒有使用,也需要注釋掉
package main
import (
"fmt"
//"time"
)
func ready() {
fmt.Println("Run func in a goroutine")
}
func main() {
go ready()
//time.Sleep(time.Second * 3)
fmt.Println("Main function done")
}
此時我們發現Goroutine好像并沒有執行,因為只有main函數中print語句輸出了結果:
那么究竟Goroutine到底有沒有被觸發呢?我們再通過這個例子看一下,這個例子中,main函數需要等待2秒,而Goroutine內執行的函數則需要等待5秒
package main
import (
"fmt"
"time"
)
func ready(s int) {
fmt.Printf("Run func in a goroutine and wait for %v\n", s)
time.Sleep(time.Second * time.Duration(s))
fmt.Printf("Run func in a goroutine and wait for %v end\n", s)
}
func main() {
mainWaitSec := 2
go ready(5)
fmt.Printf("Run Main function and wait for %v\n", mainWaitSec)
time.Sleep(time.Second * time.Duration(mainWaitSec))
fmt.Printf("Run Main function and wait for %v done\n", mainWaitSec)
}
程序運行后,雖然mian函數和ready函數中都print了開始執行的語句,但是很明顯,在Goroutine內的函數并沒有執行完成。所以我們為了更精準的控制Goroutine的并發,需要使用Channel進行控制。
Run Main function and wait for 2
Run func in a goroutine and wait for 5
Run Main function and wait for 2 done