//go 關鍵字放在方法調用前新建一個 goroutine 並讓他執行方法體 go GetThingDone(param1, param2); //上例的變種,新建一個匿名方法並執行 go func(param1, param2) { }(val1, val2) //直接新建一個 goroutine 並在 goroutine 中執行代碼塊 go { //do someting... }
//resultChan 是一個 int 類型的 channel。相似一個信封,裏面放的是 int 類型的值。 var resultChan chan int //將 123 放到這個信封裏面,供別人從信封中取用 resultChan <- 123 //從 resultChan 中取值。這個時候 result := 123 result := <- resultChan
/** * 每次調用方法會新建一個 channel : resultChan, * 同時新建一個 goroutine 來發起 http 請求並獲取結果。 * 獲取到結果以後 goroutine 會將結果寫入到 resultChan。 */ func UnblockGet(requestUrl string) chan string { resultChan := make(chan string) go func() { request := httplib.Get(requestUrl) content, err := request.String() if err != nil { content = "" + err.Error() } resultChan <- content } () return resultChan }
因爲新建的 goroutine 不會阻塞函數主流程的執行,因此調用 UnblockGet 方法會馬上獲得一個 resultChan 返回值。一旦 goroutine 執行完畢拿到結果就會寫入到 resultChan 中,這時外部就能夠從 resultChan 中獲取執行結果。php
fmt.Println(time.Now()) resultChan1 := UnblockGet("http://127.0.0.1/test.php?i=1") resultChan2 := UnblockGet("http://127.0.0.1/test.php?i=2") fmt.Println(<-resultChan1) fmt.Println(<-resultChan1) fmt.Println(time.Now())
上面兩個 http 請求是在兩個 goroutine 中並行的。總的執行時間小於 兩個請求時間和。golang
這個例子只是爲了體現 go 和 channel 的用法,有內存泄漏問題,千萬不要在線上這麼搞。由於新建的 channel 沒有 close。下次寫一個更高級一點的。併發
type RemoteResult struct { Url string Result string } func RemoteGet(requestUrl string, resultChan chan RemoteResult) { request := httplib.NewBeegoRequest(requestUrl, "GET") request.SetTimeout(2 * time.Second, 5 * time.Second) //request.String() content, err := request.String() if err != nil { content = "" + err.Error() } resultChan <- RemoteResult{Url:requestUrl, Result:content} } func MultiGet(urls []string) []RemoteResult { fmt.Println(time.Now()) resultChan := make(chan RemoteResult, len(urls)) defer close(resultChan) var result []RemoteResult //fmt.Println(result) for _, url := range urls { go RemoteGet(url, resultChan) } for i:= 0; i < len(urls); i++ { res := <-resultChan result = append(result, res) } fmt.Println(time.Now()) return result } func main() { urls := []string{ "http://127.0.0.1/test.php?i=13", "http://127.0.0.1/test.php?i=14", "http://127.0.0.1/test.php?i=15", "http://127.0.0.1/test.php?i=16", "http://127.0.0.1/test.php?i=17", "http://127.0.0.1/test.php?i=18", "http://127.0.0.1/test.php?i=19", "http://127.0.0.1/test.php?i=20" } content := MultiGet(urls) fmt.Println(content) }