goroutine 和 channel 是 Golang 的并发的两把利剑,想要把握 Golang,须要学好这两把利剑。还好这并不难,我送了两趟外卖就想明确了。

简介

Goroutine 被称为Go协程,能够通过 go 关键词创立一个协程。

go func() {    // do }()

Channel 被称为通道,通过 make 要害创立。

ch := make(chan T)// orch := make(chan T, n)

Channel 分为无缓冲和有缓冲两种,有缓冲 channel 能够通过 make 的第二个参数设置缓冲大小。

Goroutine + 无缓冲 Channel

在并发中,多个 Goroutine 之间互相通信,须要借助 channel 来实现。

上面示例代码中,启动两个协程,别离代表“点外卖的你”和“送外买的我”,咱们别离在各自的协程中繁忙着本人的事件。咱们通过 channel (门)进行通信。

对于一个无缓冲的 channel 来说,我把音讯(鸡腿外卖)给你须要通过一个无缓冲的 channel (门)。无缓冲的 channel 就意味着,我必须亲手把鸡腿送到你的手上,而不能把鸡腿挂到门把手上就去忙其余事儿

ch <- food:此时我阻塞在这里,在你磨磨唧唧开门前,我都要在这里期待。

一段时间后,你忙完了其余事件,来门口拿鸡腿food := <- ch

我把鸡腿亲手交给你之后,便能够不再阻塞,我能够持续送其余订单。你拿到外卖,开始吃鸡。

如果有一次,你饿的不行,恰好忙完了手头的所有事儿,就来门口等外卖。当我外卖没送到前,你须要在这里阻塞,期待外卖。只有我敲门把鸡腿亲手递给你,你能力开吃。

package mainimport (    "fmt"    "time")func main() {    ch := make(chan string)    go func() {        who := "外卖小哥我:"        food := "鸡腿"        fmt.Println(who, "送餐中……2s")        time.Sleep(time.Second * 2)        fmt.Println(who, "已送餐到门口,期待顾客开门取餐")        ch <- food        fmt.Println(who, "订单已送达,开始送其余单")    }()    go func() {        who := "你:"        fmt.Println(who, "期待外卖……")        time.Sleep(time.Second * 3)        fmt.Println(who, "磨磨唧唧开门中……3s")        food := <- ch        fmt.Println(who, "拿到", food, "开吃!")    }()    time.Sleep(time.Second * 5)}

Goroutine + 缓冲 Channel

无缓冲的 channel,迫使我阻塞,影响了我送外卖的效率。我决定利用缓冲容量为1的channel与你通信,进步我的送外卖效率。

于是,当我来到你的门口,我就能够把鸡腿挂到门把手上(ch <- food),这不是是我阻塞,而后我能够去送其余订单。当你忙完事件能够随时开门取餐(food := <- ch)。这样,我和你两个人都不必因为他人的事件互相期待。并行的我和你,都在循序渐进的执行本人的时候,却能通过 channel 共享数据。这就是缓冲 channel。

package mainimport (    "fmt"    "time")func main() {    ch := make(chan string, 1)    go func() {        who := "外卖小哥我:"        food := "鸡腿"        fmt.Println(who, "送餐中……2s")        time.Sleep(time.Second * 2)        fmt.Println(who, "已送餐到门口,餐挂门把手了(缓冲区)")        ch <- food        fmt.Println(who, "订单已送达,开始送其余单")    }()    go func() {        who := "你:"        fmt.Println(who, "期待外卖……")        time.Sleep(time.Second * 3)        fmt.Println(who, "磨磨唧唧开门中……3s")        food := <- ch        fmt.Println(who, "拿到", food, "开吃!")    }()    time.Sleep(time.Second * 5)}

总结

无缓冲 channel 就是须要我把鸡腿亲手交到你的手上,缓冲 channel 就是我能够把鸡腿挂到门把手上,期待你须要时来取。

看到这里你曾经明确了 Goroutine + Channel ,接下来就留一个思考题,置信听懂了的你,肯定能做进去~

思考题:请执行上面输入后果

func main() {    ch := make(chan string, 1)    go func() {        who := "送完外卖的我:"        time.Sleep(time.Second)        fmt.Println(who, "writing……1 hour")        ch <- "文章"    }()    go func() {        who := "你:"        fmt.Println(who, "摸鱼……")        read := <- ch        fmt.Println(who, "取得浏览", read, ", 并点赞")    }()    time.Sleep(time.Second * 5)}
文章来自 送了两趟外卖,我想明确了Goroutine + Channel
本文由博客一文多发平台 OpenWrite 公布!