go中的chan是動態(tài)的罐氨,因此千萬不要把chan想象成slice切片類型的數(shù)據(jù)暮现。
- 只要chan不close可以永遠發(fā)送數(shù)據(jù)和接受數(shù)據(jù)
- 如果channel里面沒有數(shù)據(jù)柠新,接收方會阻塞
- 如果沒有人正在等待channel的數(shù)據(jù)拉庵,發(fā)送方會阻塞
- 從一個close的channel取數(shù)據(jù)永遠不會阻塞, 同時獲取的數(shù)據(jù)為默認值(與定義的chan類型一致)
下面這段代碼浸间,會解釋上面這四個chan特點:
package main
import (
"net/http"
"fmt"
"sync"
)
func printUrl(url string) {
res, err := http.Get(url)
if err != nil{
fmt.Println(err)
return
}
defer res.Body.Close()
fmt.Println(url, res.Status)
}
func work2(urls chan string, wg *sync.WaitGroup) {
for{
url, ok := <- urls // 判斷取出的數(shù)據(jù)是否為false 說明chan關閉
if !ok{
break
}
printUrl(url)
}
wg.Done()
}
func work(urls chan string, wg *sync.WaitGroup) {
for i := range urls{ // chan中有一條數(shù)據(jù)會循環(huán)一次知道chan關閉
printUrl(i)
}
wg.Done()
}
func main() {
url := "http://www.baidu.com"
var u []string
for i :=0; i<15;i ++{ // 先生成一些數(shù)據(jù)
u = append(u, url)
}
wg := new(sync.WaitGroup) // 利用WaitGroup的方式協(xié)程同步
//wg.Add(5) // 可一次性添加任務總數(shù)
urlchann := make(chan string)
for i:=0; i<5 ;i++ {
wg.Add(1) // 也可每創(chuàng)建一個任務 添加一個標識
go work(urlchann, wg)
}
for _, line := range u{
urlchann <- line // 將任務需要的數(shù)據(jù)添加到隊列中
}
close(urlchann) // 關閉chan
wg.Wait()
}
代碼中的Work與Work2效果是一樣的太雨。