写点什么

Goroutine & Channel

用户头像
Vibyird
关注
发布于: 3 小时前
Goroutine & Channel

Golang 使用 CSP 模型实现并发,goroutine 和 channel 即分别对应 CSP 模型中的 Process 和 Channel。不同于多线程并发模型需要在竞态情形(race condition)下,通过复杂的锁机制确保资源正确使用。goroutine 之间可以使用 channel 进行通信。Channel 可以看成一个 FIFO 队列,对 FIFO 队列的读写都是原子的操作,不需要加锁。

Goroutine 创建

  • 在 Golang 中,Goroutine 是语言级别的支持,只需要通过一个简单的 go 关键字即可创建 Goroutine,十分快捷简单。


    go func() { // 开启Goroutine        fmt.Println("Hello World!")    }()
复制代码

Channel 创建 & 关闭

  • Channel 对象必须使用 make()函数进行创建。


channel := make(chan int) // 创建Channel
buffered_channel := make(chan int, 2) // 创建带有缓冲的Channel
close(channel) // 关闭Channel
复制代码

Channel 发送 & 接收

  • 当"<-"发送运算符在 Channel 对象右边时,代表发送操作。

  • 当"<-"接收运算符在 Channel 对象左边时,代表接收操作。可以只接收,不赋值;也可以接收完,再通过"="赋值运算符赋值给一个变量。


package main
import ( "fmt" "time")
func main() { channel := make(chan int) // 创建Channel go func() { // 开启Goroutine time.Sleep(1 * time.Second) channel <- 1 // 向Channel发送数据 }() result := <-channel // 接收Channel中的数据 fmt.Println(result)}
复制代码

select 语句

  • select 语句由多个带有 Channel 的发送或接收操作的 case 组成。

  • 一组 select 语句执行,只会处理第一个就绪的发送或接收 case。


package main
import ( "fmt" "time")
func main() { channel1 := make(chan int) // 创建Channel1 channel2 := make(chan int) // 创建Channel2 go func() { // 开启Goroutine1 time.Sleep(100 * time.Millisecond) channel1 <- 1 // 向Channel1发送数据 }() go func() { // 开启Goroutine2 time.Sleep(100 * time.Millisecond) channel2 <- 2 // 向Channel2发送数据 }() select { // 同时等待接收Channel1和Channel2的数据,只要有一个就绪,即完成对应case的处理 case result := <-channel1: fmt.Println(result) case result := <-channel2: fmt.Println(result) }}
复制代码

for … range 语句

  • for … range 语句可以迭代接收 Channel 中的数据,直到 Channel 被关闭。


package main
import ( "fmt" "time")
func main() { channel := make(chan int) // 创建Channel go func() { for i := 0; i < 10; i++ { time.Sleep(100 * time.Millisecond) channel <- i // 不断向Channel发送数据 } close(channel) // 关闭Channel }() for result := range channel { // 迭代Channel中的数据,并打印出来 fmt.Println(result) }}
复制代码

优雅地实现处理超时

  • golang 标准库中的 time.After()函数的返回值,即是一个 channel。

  • 通过和 select 语句相结合,我们优雅地实现处理超时。


package main
import ( "fmt" "time")
func main() { channel := make(chan int) // 创建Channel go func() { // 开启Goroutine time.Sleep(1 * time.Second) channel <- 1 // 向Channel发送数据 }()
select { case result := <-channel: // 接收Channel中的数据 fmt.Println(result) case <-time.After(100 * time.Millisecond): fmt.Println("time out") }}
复制代码


发布于: 3 小时前阅读数: 6
用户头像

Vibyird

关注

还未添加个人签名 2017.10.19 加入

还未添加个人简介

评论

发布
暂无评论
Goroutine & Channel