Go 并发:Channel 通道

在上一篇文章《Go 并发机制:Goroutine》中,我们讨论了 Go 如何使用 goroutine 实现并发。本文我们继续讨论 goroutine 如何利用 channel 来进行通信。

什么是 channel

Channel,通道,可看作是 goroutine 进行通信的管道(pipe)。跟水可以在管道中从一端流向另一端类似,数据也可以通过通道从一端发送,从另一端接收。

声明 channel

每一个通道都有一个具体的类型,即这个通道允许传输的数据类型。

ch T

一个类型为 T 的通道。

通道的零值为 nil,可以使用 make 来定义通道。例如:

package main

import "fmt"

func main() {
   
   
	var a chan int
	if a == nil {
   
   
		fmt.Println("channel a is nil, going to define it")
		a = make(chan int)
		fmt.Printf("Type of a is %T", a)
	}
}

上面的程序中,首先声明了 a 通道,且a 通道的类型为 int。由于 a 通道开始的值为 nil,接下来进行通道的定义。

运行程序,输出:

channel a is nil, going to define it
Type of a is chan int

通常来说,也可以使用短变量声明来定义一个通道:

a := make(chan int)  

上面的代码,同样定义了一个类型为 int 的通道。

通过 channel 收发数据

可以通过通道收发数据,例如:

data := <- a // 从通道 a 接收数据 
a <- data // 往通道 a 发送数据

通过通道发送和接收数据都使用 <- 操作符。第一行中,箭头指向变量 data,表示从通道中接收数据,并保存至变量 data 中。
第二行中,箭头指向通道 a,表示往通道 a 发送数据。

默认情况下,从通道接收数据和往通道发送数据都会阻塞。对于发送方来说,发送数据将会一直阻塞,直到另一个 goroutine 从通道读取数据。同理,对于接收方来说,接收数据将会一直阻塞,直到另一个 goroutine 往通道发送数据。
通道的这种特性有利于 goroutine 在不显式使用锁或者条件变量的情况进行有效的通信。

例子

我们继续以上一篇文章《Go 并发机制:Goroutine》中的程序为例,改用通道来实现。

为便于对照,这里附上原程序:

package main

import (  
    "fmt"
    "time"
)

func hello() {
   
     
    fmt.Println("Hello world goroutine")
}

func main() {
   
     
    go hello()
    time.Sleep(1 * time.Second)
    fmt.Println("main function")
}

为避免 main goroutine 没有等待 hello goroutine 执行完毕就直接退出,main goroutine 使用了 Sleep 睡眠以等待 1 秒时间。如何改用通道更优雅地实现类似的功能呢?

package main

import (
	"fmt"
)

func hello(done chan bool) {
   
   
	fmt.Println(<
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值