无buffer的chan,buffer=0的chan
从ch中取数据。
如果ch中没有传入数据,程序将一直阻塞在<-ch这里
//无buffer的chan
ch := make(chan int)
//从ch中取数据
<-ch//如果ch中没有传入数据,程序将一直阻塞在这里
往ch中写数据。
如果ch中没有可以写入数据,则程序会阻塞在ch<-1这里
//无buffer的chan
ch := make(chan int)
ch<-1
有buffer的chan
只影响chan的写入,如果chan的buffer已经满了(比如,chan中的数据没有被消费或者chan中的数据消费比生产要慢),则程序会阻塞在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的发送操作总是在接受前完成(操作是指执行顺序,而不是代码编写顺序)。
注意:close chan,<-chan将接收到chan的零值
不建议的使用方式
end := make(chan int64, 0)
var a int64
go func() {
a = <-end
fmt.Println(999)//此行代码很有可能无法输出
}()
end <- 1
fmt.Println(a)
因为buffer为0,end <- 1此行会被阻塞,直到a = <-end被执行,一旦a = <-end被执行,end <- 1会立刻发送数据,程序执行fmt.Println(a),执行到这里,程序就结束了。fmt.Println(999)很大可能无法及时执行。
如果buffer不为0,写数据不会被阻塞,则程序立刻结束了,goroutine中的代码很可能无法执行。
建议的使用方式
先写数据,再读数据。
解释:写数据一般可能会有时间消耗,比如写入的数据是从cache或者db中读取的。在goroutine中执行耗时操作也比较合理。
end := make(chan int64)
go func() {
end <- 1
}()
fmt.Println(<-end)
读数据也可以在goroutine中执行
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)