Go语言通道(channel)的创建和使用(非常详细,附带实例)
通道是 Go 语言在两个或多个协程(goroutine)之间的一种通信方式。通道可以让一个协程给另一个协程发送消息。当需要在协程之间共享一个数据资源时,通道是确保同步交换数据资源的方法。
协程与通道的关系如下图所示:

图 1 协程与channel(通道)的关系
多个协程为了争抢数据资源,势必会降低执行效率。为了保证执行效率不降低,协程之间通过通道进行通信,确保同一时刻只有一个协程访问通道,并执行发送和接收数据的操作。
通道就像队列一样,遵循“先入先出”的规则,保证发送和接收数据的顺序。
声明通道类型的语法格式如下:
为了创建通道,需要使用 make() 函数。创建通道的语法格式如下:
在实际开发中,可以先声明通道,再创建通道。代码如下:
还可以省去声明通道的步骤,直接使用 make() 函数创建通道。代码如下:
例如,创建一个可以传输任意类型的数据的通道,分别让其发送数字 711 和字符串“hello world”。关键代码如下:
使用通道接收数据也要使用特殊的操作符“<-”,并有 4 种语法格式:
① 发送数据操作将被持续阻塞,直到通道传输的数据被接收。语法格式如下:
② 通道传输的数据被接收且不会发送阻塞。语法格式如下:
③ 发送数据操作被持续阻塞,直到接收通道传输的数据,但是接收到的数据会被忽略。语法格式如下:
④ 使用 for range 语句接收通道传输的数据。语法格式如下:
下面的实例演示如何遍历通道传输的数据。
【实例】遍历通道传输的数据。创建传输int类型数据的通道。为匿名函数创建协程,其作用是使用通道发送数字 0~5。遍历并打印通道传输的数据。代码如下:
close() 函数的语法格式如下:
协程与通道的关系如下图所示:

图 1 协程与channel(通道)的关系
多个协程为了争抢数据资源,势必会降低执行效率。为了保证执行效率不降低,协程之间通过通道进行通信,确保同一时刻只有一个协程访问通道,并执行发送和接收数据的操作。
通道就像队列一样,遵循“先入先出”的规则,保证发送和接收数据的顺序。
Go语言通道的声明和创建
在 Go 语言中,通道是一种特殊的数据类型。通道需要一个类型修饰。这样,通道的类型就是在其内部传输的数据的类型。声明通道类型的语法格式如下:
var name chan type参数说明如下:
- var:Go 语言关键字,用于声明变量;
- name:通道的名称;
- chan:Go 语言关键字,通道类型;
- type:在通道内部传输的数据的类型。
为了创建通道,需要使用 make() 函数。创建通道的语法格式如下:
name := make(chan type)参数说明如下:
- name:通道的名称;
- make:make() 函数,用于创建通道;
- chan:Go 语言关键字,通道类型;
- type:在通道内部传输的数据的类型。
在实际开发中,可以先声明通道,再创建通道。代码如下:
var chel chan string chel = make(chan string)
还可以省去声明通道的步骤,直接使用 make() 函数创建通道。代码如下:
chel := make(chan string)
Go语言通道的基本操作
创建通道后,就可以使用通道执行发送和接收数据的操作了。1) 使用通道发送数据
使用通道发送数据需要使用特殊的操作符“<-”,其语法格式如下:name <- value参数说明如下:
- name:已经创建的通道的名称;
- value:值,可以是变量、常量、表达式或函数返回值等;值的类型必须与在通道内部传输的数据的类型保持一致。
例如,创建一个可以传输任意类型的数据的通道,分别让其发送数字 711 和字符串“hello world”。关键代码如下:
//创建传输任意类型数据的通道 chel := make(chan interface{}) //使用通道发送数字711 chel <- 711 //使用通道发送字符串hello world chel <- "hello"把在通道内部传输的数据的类型设置为空接口类型,该通道就能够传输任意类型的数据。
2) 使用通道接收数据
使用通道接收和发送数据具有以下特性:- 如果没有接收通道传输的数据,那么发送数据操作将被持续阻塞;
- 如果接收了通道传输的数据,但尚未执行发送数据操作,那么接收数据操作将被持续阻塞;
- 通道一次只能传输一个数据。
使用通道接收数据也要使用特殊的操作符“<-”,并有 4 种语法格式:
① 发送数据操作将被持续阻塞,直到通道传输的数据被接收。语法格式如下:
data := <-name参数说明如下:
- data:变量名;
- name:通道的名称。
② 通道传输的数据被接收且不会发送阻塞。语法格式如下:
data, ok = <-name参数说明如下:
- ok:表示通道传输的数据是否被接收。
③ 发送数据操作被持续阻塞,直到接收通道传输的数据,但是接收到的数据会被忽略。语法格式如下:
<-name
④ 使用 for range 语句接收通道传输的数据。语法格式如下:
for data := range name { }通道传输的数据是可以遍历的,遍历的结果就是接收到的数据。
下面的实例演示如何遍历通道传输的数据。
【实例】遍历通道传输的数据。创建传输int类型数据的通道。为匿名函数创建协程,其作用是使用通道发送数字 0~5。遍历并打印通道传输的数据。代码如下:
package main import ( "fmt" "time" ) func main() { ch := make(chan int) // 创建传输int类型数据的通道 go func() { for i := 0; i < 6; i+++ { ch <- i // 使用通道发送数字 0~5 time.Sleep(1 * time.Second) // 延时 1s } }() // 遍历通道传输的数据 for data := range ch { fmt.Println(data) // 如果遍历的结果是 5 if data == 5 { break // 则不再接收通道传输的数据 } } }运行结果如下:
0
1
2
3
4
5
3) 关闭通道
通道使用 Go 语言内置的 close() 函数设置标识,告诉 Go 程序当前通道已完成发送数据的操作。在使用 close() 函数关闭通道后,通道不再执行发送数据的操作。close() 函数的语法格式如下:
close(name)参数说明如下:
- name:已经创建的通道的名称。