goroutine 是 Go语言程序的并发体,channels 是它们之间的通信机制。
一个 channels 是一个通信机制,它可以让一个 goroutine 通过它给另一个 goroutine 发送值信息。每个 channel 都有一个特殊的类型,也就是 channels 可发送数据的类型。一个可以发送 int 类型数据的 channel 一般写为 chan int。
Go语言提倡使用通信的方法代替共享内存,当一个资源需要在 goroutine 之间共享时,通道在 goroutine 之间架起了一个管道,并提供了确保同步交换数据的机制。声明通道时,需要指定将要被共享的数据的类型。可以通过通道共享内置类型、命名类型、结构类型和引用类型的值或者指针。
Go语言中的通道(channel)是一种特殊的类型。在任何时候,同时只能有一个 goroutine 访问通道进行发送和获取数据。goroutine 间通过通道就可以通信。
通道像一个传送带或者队列,总是遵循先入先出(First In First Out)的规则,保证收发数据的顺序。
通道本身需要一个类型进行修饰,就像切片类型需要标识元素类型。通道的元素类型就是在其内部传输的数据类型,声明如下:
var 通道变量 chan 通道类型
// 通道类型:通道内的数据类型
// 通道变量:保存通道的变量
chan 类型的空值是 nil,声明后需要配合 make 后才能使用。
通道是引用类型,需要使用 make 进行创建,格式如下:
通道实例 := make(chan 数据类型)
数据类型:通道内传输的元素类型。
通道实例:通过make创建的通道句柄。
通道创建后,就可以使用通道进行发送和接收操作。
通道的发送使用特殊的操作符<-,将数据通过通道发送的格式为:
通道变量 <- 值
// 通道变量:通过make创建好的通道实例。
// 值:可以是变量、常量、表达式或者函数返回值等。值的类型必须与ch通道的元素类型一致。
使用 make 创建一个通道后,就可以使用<-向通道发送数据,代码如下:
// 创建一个空接口通道
ch := make(chan interface{})
// 将0放入通道中
ch <- 0
// 将hello字符串放入通道中
ch <- "hello"
把数据往通道中发送时,如果接收方一直都没有接收,那么发送操作将持续阻塞。Go 程序运行时能智能地发现一些永远无法发送成功的语句并做出提示,代码如下:
package main
func main() {
// 创建一个整型通道
ch := make(chan int)
// 尝试将0通过通道发送
ch <- 0
}
运行代码,报错:fatal error: all goroutines are asleep - deadlock!
报错的意思 :运行时发现所有的 goroutine(包括main)都处于等待 goroutine。也就是说所有 goroutine 中的 channel 并没有形成发送和接收对应的代码。
关于通道阻塞的问题请继续观看后面内容。