【Day 23】Go 基础小笔记 IV:goroutine、channel

身为并发(concurrency)小能手的 Go 的重要特色
有了 channel 好像几乎不需要 lock (例如 mutex)了呢

2021/10/14 更新:Go 与 concurrency

虽然还有一些东西没介绍到,例如 closure(闭包),
但感觉还是赶快看看别的程序码会比较好玩一点XD
明天要爬山不知道有没有空好好来看 被选召的 Gopher 们,从零开始探索 Golang, Istio, K8s 数码微服务世界 系列 系列呢?

Go 与 concurrency

Go 的特点就是不需要特别 import 其他的模组,
内建的 go 这个关键字就能够开启类似 thread 的 goroutine
并透过 Go Runtime Scheduler 排程使这些 goroutines 轮流跑。

至於 parallelism 要看硬体支援,也需要额外设定。

如果对於 concurrency(并发) / parallelism(并行) 的差别不熟悉可以参考 Concurrency is not parallelism 或 Google 图片。

goroutines

只要在 function 前加一个 go 就可以开一个 goroutine(thread)
go f(x, y)
main 本身也是一个 goroutine

channel

我个人觉得没有很好理解的观念,注意一开始不要把 channel 当成 buffer 理解。
Go 的并发:Goroutine 与 Channel 介绍,以 「推入」「拉出」channel 来比喻,我觉得比 send / receive 还好懂一点。

ch := make(chan int) // create a channel
ch <- v    // Send v to channel ch.
v := <-ch  // Receive from ch, and
           // assign value to v.

unbuffered channel

有一方在 send / receive 时,除非有另一方做 receive / send,不然就会 block(阻塞)在那

但我自己感觉只有 <- 才有 block 住?Channels的第20行的y拔掉後,main 就不会再等,直接 exit。

  • for i := range ch 直到 close(ch)

  • 永远只有 sender 该做 close 的动作。
    因为只有他知道什麽时候再也不会 send 任何东西了,而如果给关闭的 channel 送东西的话会导致 panic。

  • channel 不是档案不一定要 close
    只有当 receiver 在跑回圈,例如印出 channel 接到的值,因为需要知道 sender 已经传完了所以需要 close。

  • select
    当某个 goroutine 要拉取 channel 的资料而可能需要等待时,当下就 block 住而不能处理其他事情。
    如果这是处理画面的 goroutine,就等於卡在那而不能有状态条或其他等等回馈。

使用 select,case <- ch 先试着拉,如果塞住就看别的 case,
直到有一个 channel 有送到值 或是 最後使用 default case。

select {
        case <-ch: // Channel 中有资料执行此区域
            fmt.Println("main goroutine finished")
            return
        default: // Channel 阻塞的话执行此区域
            fmt.Println("WAITING...")
            time.Sleep(500 * time.Millisecond)
        }

select 有点像 switch,但每个 case 都是拉拉看某个 channel 资料是否另一方送来了。

buffered channel

推入 / 拉出的时间不对等时(例如有一方有比较复杂的运算),就会造成等待。

如果有 buffer,推入时就不用等到有人拉出才能继续推了;
只有当 buffer 满的时候会 block,也就是不能再推入了。

ch := make(chan int, 2)


<<:  [day-23] Python-基本认识回圈!(Part .2)

>>:  Day23:传入 JSON 文件

我们的基因体时代-AI, Data和生物资讯 Day10-基因疗法中之腺病毒载体与机器学习

上一篇我们的基因体时代-AI, Data和生物资讯 Day09-合成生物学与机器学习分享合成生物学领...

[Day 36] 自我介绍後台及前台(五) - 前台的自我介绍页

接下来要写自我介绍页, 自我介绍页使用 routes/web.php 里面的 Route::grou...

[Day - 17 ] - Spring 导入选择器原理与开发

Abstract 我们前面已经讨论了相当多种取得Bean的方法,如:自动注入(@Autowired、...

POCO_设定所有Table继承同一个class

因为专案刚好需要用到 所以纪录一下参数在哪边 纪录一下 使用Visual Studio Entity...

[Day 30]30天挑战成功!同场加码Azure Machine Learning!

今天是最後一天啦!但学习的路还尚未中断!笔者今天想聊聊不一样的,看到标题应该可以猜到,我们今天要来聊...