無buffer的chan,buffer=0的chan
從ch中取數(shù)據(jù)。
如果ch中沒有傳入數(shù)據(jù),程序?qū)⒁恢弊枞?lt;-ch這里
//無buffer的chan
ch := make(chan int)
//從ch中取數(shù)據(jù)
<-ch//如果ch中沒有傳入數(shù)據(jù),程序?qū)⒁恢弊枞谶@里
往ch中寫數(shù)據(jù)。
如果ch中沒有可以寫入數(shù)據(jù),則程序會阻塞在ch<-1這里
//無buffer的chan
ch := make(chan int)
ch<-1
有buffer的chan
只影響chan的寫入,如果chan的buffer已經(jīng)滿了(比如,chan中的數(shù)據(jù)沒有被消費(fèi)或者chan中的數(shù)據(jù)消費(fèi)比生產(chǎn)要慢),則程序會阻塞在ch<-1這里
//有buffer的chan
ch := make(chan int,2)
ch<-1
fmt.Println(1)
ch<-1
fmt.Println(2)
ch<-1//會阻塞在這里
fmt.Println(3)
無buffer的chan的發(fā)送操作總是在接受前完成(操作是指執(zhí)行順序,而不是代碼編寫順序)。
注意:close chan,<-chan將接收到chan的零值
不建議的使用方式
end := make(chan int64, 0)
var a int64
go func() {
a = <-end
fmt.Println(999)//此行代碼很有可能無法輸出
}()
end <- 1
fmt.Println(a)
因?yàn)閎uffer為0,end <- 1此行會被阻塞,直到a = <-end被執(zhí)行,一旦a = <-end被執(zhí)行,end <- 1會立刻發(fā)送數(shù)據(jù),程序執(zhí)行fmt.Println(a),執(zhí)行到這里,程序就結(jié)束了。fmt.Println(999)很大可能無法及時執(zhí)行。
如果buffer不為0,寫數(shù)據(jù)不會被阻塞,則程序立刻結(jié)束了,goroutine中的代碼很可能無法執(zhí)行。
建議的使用方式
先寫數(shù)據(jù),再讀數(shù)據(jù)。
解釋:寫數(shù)據(jù)一般可能會有時間消耗,比如寫入的數(shù)據(jù)是從cache或者db中讀取的。在goroutine中執(zhí)行耗時操作也比較合理。
end := make(chan int64)
go func() {
end <- 1
}()
fmt.Println(<-end)
讀數(shù)據(jù)也可以在goroutine中執(zhí)行
count := 0
end := make(chan int64, 20)
go func() {
for i := 0; i < 10; i++ {
end <- int64(i)
}
}()
go func() {
for v := range end {
count++
fmt.Println(v, count)
}
}()
http.HandleFunc("/state", func(writer http.ResponseWriter, request *http.Request) {
io.WriteString(writer, "count is "+strconv.Itoa(count))
})
http.ListenAndServe(":7777", nil)