一、非缓冲通道
之前学习的所有通道基本上都没有缓冲。发送和接收到一个未缓冲的通道是阻塞的。
一次发送操作对应一次接收操作,对于一个goroutine来讲,它的一次发送,在另一个goroutine接收之前都是阻塞的。同样的,对于接收来讲,在另一个goroutine发送之前,它也是阻塞的。
二、缓冲通道
缓冲通道就是指一个通道,带有一个缓冲区。发送到一个缓冲通道只有在缓冲区满时才被阻塞。类似地,从缓冲通道接收的信息只有在缓冲区为空时才会被阻塞。
可以通过将额外的容量参数传递给make函数来创建缓冲通道,该函数指定缓冲区的大小。
语法:
ch := make(chan type, capacity)
上述语法的容量应该大于0,以便通道具有缓冲区。默认情况下,无缓冲通道的容量为0,因此在之前创建通道时省略了容量参数。
三、示例代码
以下的代码中,chan通道,是带有缓冲区的。
package mainimport ( "fmt" "strconv" "time")func main() { ch1 := make(chan int) //非缓存的通道 fmt.Println(len(ch1), cap(ch1)) //0 0 //ch1 <- 100//阻塞的,需要其他的goroutine解除阻塞,否则deadlock ch2 := make(chan int, 5) //缓存的通道,缓存区大小是5 fmt.Println(len(ch2), cap(ch2)) //0 5 ch2 <- 100 // fmt.Println(len(ch2), cap(ch2)) //1 5 //ch2 <- 200 //ch2 <- 300 //ch2 <- 400 //ch2 <- 500 //ch2 <- 600 fmt.Println("--------------") ch3 := make(chan string, 4) go sendData3(ch3) for { time.Sleep(1*time.Second) v, ok := <-ch3 if !ok { fmt.Println("读完了,,", ok) break } fmt.Println("t读取的数据是:", v) } fmt.Println("main...over...")}func sendData3(ch3 chan string) { for i := 0; i < 10; i++ { ch3 <- "数据" + strconv.Itoa(i) fmt.Println("子goroutine,写出第", i, "个数据") } close(ch3)}运行结果:



