定义
channel是一个引用类型,类似队列,遵循的是先进先出规则,声明格式:var username chan type。
如以下示例:
// 声明一个传递整形的通道
var ch1 chan int
// 声明一个传递int切片的通道
var ch2 chan []int
创建
channel声明后需要进行make初始化才可使用,不声明则为空值nil。
func main() {
var ch chan int
fmt.Println(ch) // nil
ch1 := make(chan int, 3)
fmt.Println(ch1) // 0xxxxxxxx
}channel有三种操作,分别是发送、接收、关闭。发送和接收都使用<-符号。
例如有一个ch通道。
使用ch通道发送数据为:ch <- 10
接收ch通道发出的数据为:a := <- ch,如果要忽略通道发出的数据,则什么都不写即可:<- ch
关闭ch通道:close(ch)
关闭通道需要注意:只有告诉接收方所有的数据都发送完毕,才需关闭通道,而通道是可以被垃圾回收机制回收的,所以不关也可以。
示例:
func main() {
ch := make(chan int, 3) // 这时ch通道没有任何数据,所以接收时会报deadlock错误
a := <-ch
fmt.Println(a)
ch <- 10
b := <-ch
fmt.Println(b) // 10
}无缓冲区通道
无缓冲区通道即初始化时没有指定该通道的容量大小。
func main() {
ch := make(chan int)
ch <- 10
fmt.Println("success")
}上面就是一个无缓冲区通道的例子,make时没有定义通道大小,运行时会报deadlock错误,因为无缓冲区通道无法发送数据,所以程序会阻塞在ch <- 10这一行,造成死锁。
解决办法就是通过启用goroutine去接收值,示例如下:
func recv(c chan int) {
ret := <-c
fmt.Println("receive success", ret)
}
func main() {
ch := make(chan int)
go recv(ch)
ch <- 10
fmt.Println("send success")
}注意:当从无缓冲区通道接受值时,该通道必须有值再发送。同理,发送值时,也必须有接收的。缺一不可,所以无缓冲区通道也叫同步通道,发送和接收是同步进行的。
有缓冲区通道
make初始化给了容量大小就是有缓冲区通道,可以使用len查看通道目前存有几个元素,cap查看通道的容量。
func main() {
ch := make(chan int, 3)
ch <- 10
ch <- 20
fmt.Println(len(ch)) // 2
fmt.Println(cap(ch)) // 3
fmt.Println(<-ch) // 10
fmt.Println(<-ch) // 20
fmt.Println(len(ch))
}通道遍历
通道遍历可以使用range,如下示例:
func main() {
ch := make(chan int, 10)
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
for v := range ch {
fmt.Println(v)
}
}注意:ch通道在发送值后,使用close关闭了,如果此处不关闭,下面range遍历时就会报死锁,因为循环接收值时,接收完后,还会循环取,这时已经没值了,就会不断循环造成死锁,所以需要进行关闭。
单向通道
函数中允许参数为通道类型,但有时候可能只需要该通道来接收值或者发送值,这时就需要对该通道设置单向设置。设置时只需要在函数参数上添加<-符号即可。
// a函数的通道参数只能传入值,即只写的单向通道
func a(ch chan<- int) {
fmt.Println(ch)
}
// b函数的通道参数只能输出值,即只读的单向通道
func b(ch <-chan int) {
fmt.Println(ch)
}示例如下:
func onlyWrite(ch chan<- int) {
for i := 0; i < 10; i++ {
ch <- i
}
close(ch)
}
func onlyRead(read <-chan int, write chan<- int) {
for v := range read {
write <- v
}
close(write)
}
func chPrint(ch <-chan int) {
for v := range ch {
fmt.Println(v)
}
}
func main() {
ch1 := make(chan int)
ch2 := make(chan int)
go onlyWrite(ch1)
go onlyRead(ch1, ch2)
chPrint(ch2)
}通道关闭的特点
1,通道关闭后,再发送值会导致panic异常。
2,通道关闭后,再接收值会一直进行数据的读取,直到读完。
3,通道关闭后,再进行关闭会导致panic异常。
通道总结
最后
以上就是名字长了才好记最近收集整理的关于go channel的全部内容,更多相关go内容请搜索靠谱客的其他文章。
发表评论 取消回复