Go并发编程
Go语言 通道Channel
Go语言的并发模型是CSP(Communicating Sequential Processes),提倡通过通信共享内存而不是通过共享内存而实现通信。 Go 语言中的通道(channel)是一种特殊的类型。通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。每一个通道都是一个具体类型的导管,也就是声明channel的时候需要为其指定元素类型。 Go语言提倡使用通信的方法代替共享内存,当一个资源需要在 goroutine 之间共享时,通道在 goroutine 之间架起了一个管道,并提供了确保同步交换数据的机制。声明通道时,需要指定将要被共享的数据的类型。可以通过通道共享内置类型、命名类型、结构类型和引用类型的值或者指针。  ## 通道的特性 Go语言中的通道(channel)是一种特殊的类型。在任何时候,同时只能有一个 goroutine 访问通道进行发送和获取数据。goroutine 间通过通道就可以通信。 通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。 ## 声明通道类型 通道本身需要一个类型进行修饰,就像切片类型需要标识元素类型。通道的元素类型就是在其内部传输的数据类型,声明如下: ```go var 通道变量 chan 通道类型 ``` ## 创建通道 通道是引用类型,需要使用 make 进行创建,格式如下: ```go 通道实例 := make(chan 数据类型) ``` ```go ch1 := make(chan int) // 创建一个整型类型的通道 ch2 := make(chan interface{}) // 创建一个空接口类型的通道, 可以存放任意格式 type Equip struct{ /* 一些字段 */ } ch2 := make(chan *Equip) // 创建Equip指针类型的通道, 可以存放*Equip ``` ## channel操作 通道有发送(send)、接收(receive)和关闭(close)三种操作。 发送和接收都使用<-符号。 通过调用内置的close函数来关闭通道: close(ch) #### 使用通道发送数据 >把数据往通道中发送时,如果接收方一直都没有接收,那么发送操作将持续阻塞。 ```go // 创建一个空接口通道 ch := make(chan interface{}) // 将0放入通道中 ch <- 0 // 将hello字符串放入通道中 ch <- "hello" ``` #### 使用通道接收数据 通道接收有如下特性: - ① 通道的收发操作在不同的两个 goroutine 间进行。由于通道的数据在没有接收方处理时,数据发送方会持续阻塞,因此通道的接收必定在另外一个 goroutine 中进行。 - ② 接收将持续阻塞直到发送方发送数据。如果接收方接收时,通道中没有发送方发送数据,接收方也会发生阻塞,直到发送方发送数据为止。 - ③ 每次接收一个元素。通道一次只能接收一个数据元素。 #### 通道的数据接收一共有以下 4 种写法: - 1) 阻塞接收数据: ```go data := <-ch ``` - 2) 非阻塞接收数据 使用非阻塞方式从通道接收数据时,语句不会发生阻塞,格式如下: ```go data, ok := <-ch ``` data:表示接收到的数据。未接收到数据时,data 为通道类型的零值。 ok:表示是否接收到数据。 - 3) 接收任意数据,忽略接收的数据 阻塞接收数据后,忽略从通道返回的数据,格式如下: ```go <-ch ``` 执行该语句时将会发生阻塞,直到接收到数据,但接收到的数据会被忽略。这个方式实际上只是通过通道在 goroutine 间阻塞收发实现并发同步。 - 4) 循环接收 通道的数据接收可以借用 for range 语句进行多个元素的接收操作,格式如下: ```go for data := range ch { } ``` ```go // 遍历接收通道数据 for data := range ch { // 打印通道数据 fmt.Println(data) // 当遇到数据0时, 退出接收循环 if data == 0 { break } } ``` #### 关闭通道 我们通过调用内置的close函数来关闭通道。 ```go close(ch) ``` 关于关闭通道需要注意的事情是,只有在通知接收方goroutine所有的数据都发送完毕的时候才需要关闭通道。通道是可以被垃圾回收机制回收的,它和关闭文件是不一样的,在结束操作之后关闭文件是必须要做的,但关闭通道不是必须的。 关闭后的通道有以下特点: 对一个关闭的通道再发送值就会导致panic。 对一个关闭的通道进行接收会一直获取值直到通道为空。 对一个关闭的并且没有值的通道执行接收操作会得到对应类型的零值。 关闭一个已经关闭的通道会导致panic。 ## channel常见的异常 
顶部
收展
底部
[TOC]
目录
Go语言 并发
Go语言 goroutine(轻量级线程)
Go语言 通道Channel
Go语言 竞争状态
Go语言 死锁、活锁和饥饿
Go语言 select
相关推荐
Go基础
Go数据类型
Go函数
Go面向对象
Go数据操作