还在学习中,理解的更为透彻了再来总结。缓存
无缓存channel每一个发送和接收操做的同步性,由于因为无缓冲区,因此其余goroutine的发送会被阻塞在那边,只有接收完毕后,某个goroutine才能写入这个channel。异步
有缓冲区channel会使得读写routine(或者说是收发goroutine)是异步的,只要再缓冲区没有满,其余的协程就能继续写,缓冲区不空,其余的协程就能继续读。学习
若是是unbuffered channel,那么发送者的goroutine会被阻塞,直到被别的goroutine接收后才会继续往下走。以下这段代码是错误的,会一直被阻塞,go run的时候报错:spa
1 func main() { 2 ch := make(chan int) //unbuffered channel 3 a := 10 4 ch <- a //blocked here 5 b := <-ch 6 fmt.Println(b) 7 }
fatal error: all goroutines are asleep - deadlock!code
goroutine 1 [chan send]协程
有两种方法修改,第一种改为buffered channel:blog
1 func main() { 2 ch := make(chan int, 1) //buffered channel 3 a := 10 4 ch <- a 5 b := <-ch 6 fmt.Println(b) 7 } //正确输出10
第二种是将发送这个动做放在一个goroutine中,这样就不会阻塞主goroutine,主goroutine中的接收动做就得以完成:get
1 func main() { 2 ch := make(chan int) //unbuffered channel 3 a := 10 4 go func() { ch <- a }() // new a goroutine 5 b := <-ch 6 fmt.Println(b) 7 }
ubuffered channel的发送和接收goroutine之间是同步的,不是异步的。带缓冲区的channel是异步的。同步
channel的零值是nil,注意:若是其通道是nil,它将永远不会被选择。it
一、若是channel已经关闭,继续往它发送数据会致使panic: send on closed channel
二、关闭一个已经关闭的channel,会致使panic:close of closed channel
三、读取一个已经关闭的channel,能够读出没有读完的channel。读完后会读到零值。能够屡次读取。
1 func test(){ 2 ch:=make(chan int,3) 3 ch<-3 4 ch<-2 5 ch<-1 6 close(ch) 7 fmt.Print(<-ch) 8 fmt.Print(<-ch) 9 fmt.Print(<-ch) 10 fmt.Print(<-ch) 11 fmt.Print(<-ch) 12 } 13 //right
不能经过判断返回值是不是零值(包括nil)来判断channel是否已经关闭,应为nil能够做为值传递给channel:
1 func main() { 2 ch := make(chan interface{}, 10) 3 ch <- nil 4 5 a := <-ch 6 fmt.Println(a) //输出nil,没有close 7 }