Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Speaker Deck
PRO
Sign in
Sign up for free
Go言語による並行処理「4.4 orチャネル」の図
Hiroyuki ANAI
October 05, 2021
Technology
0
190
Go言語による並行処理「4.4 orチャネル」の図
コードを読んでいて混乱したので図にしました。
Hiroyuki ANAI
October 05, 2021
Tweet
Share
More Decks by Hiroyuki ANAI
See All by Hiroyuki ANAI
Step Functionsの設計時に知っておいたほうがいいかもしれないこと
pirosikick
0
160
サイボウズWebフロントエンド脱レガシーの今までとこれから
pirosikick
5
15k
@cybozu/eslint-configから学ぶ、全社共通ESLint configの運用
pirosikick
4
1.4k
Web Share Target API #w3fukuoka
pirosikick
0
480
Google I/O '19のWebをまとめる会
pirosikick
2
670
PuppeteerでいらないCSSを消す
pirosikick
24
25k
Progressive Hydration #react_fukuoka
pirosikick
5
1.2k
WebFEのテストにおける気持ちの変遷
pirosikick
0
320
私が考えるReactのよさ #fukuokajs
pirosikick
2
610
Other Decks in Technology
See All in Technology
ユーザーテストガイドライン VERSION 2.0
kouzoukaikaku
0
1.4k
SmartHRからOktaへのSCIM連携で作り出すHRドリブンのアカウント管理
jousysmiler
1
120
AWS Cloud Forensics & Incident Response
e11i0t_4lders0n
0
390
WebLogic Server for OCI 概要
oracle4engineer
PRO
3
880
S3とCloudWatch Logsの見直しから始めるコスト削減 / Cost saving S3 and CloudWatch Logs
shonansurvivors
0
250
OpenShiftクラスターのアップグレード自動化への挑戦! / OpenShift Cluster Upgrade Automation
skitamura7446
0
160
API連携に伴う規制と対応 / Regulations and responses to API linkage
moneyforward
0
160
立ち止まっても、寄り道しても / even if I stop, even if I take a detour
katoaz
0
710
SSMパラメーターストアでクロススタック参照の罠を回避する
shuyakinjo
0
7.4k
MarvelClient Upgrade 64bit クライアントへの自動アップグレード設定
mitsuru_katoh
0
160
20230123_FinJAWS
takuyay0ne
0
120
オブザーバビリティのベストプラクティスと弥生の現状 / best practices for observability and YAYOI’s current state
yayoi_dd
0
100
Featured
See All Featured
5 minutes of I Can Smell Your CMS
philhawksworth
198
18k
Fight the Zombie Pattern Library - RWD Summit 2016
marcelosomers
227
16k
Bash Introduction
62gerente
601
210k
Automating Front-end Workflow
addyosmani
1351
200k
Practical Orchestrator
shlominoach
178
8.9k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
270
12k
A Modern Web Designer's Workflow
chriscoyier
689
180k
Templates, Plugins, & Blocks: Oh My! Creating the theme that thinks of everything
marktimemedia
15
1.2k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
236
1.1M
The Invisible Customer
myddelton
113
12k
Streamline your AJAX requests with AmplifyJS and jQuery
dougneiner
128
8.8k
Clear Off the Table
cherdarchuk
79
290k
Transcript
GoݴޠʹΑΔ ฒߦॲཧ 4.4 orνϟωϧͷਤ @pirosikick
• var or(channels ...<-chan interface{}) <-chan interface{} • "1つ以上のdoneチャネルを1つのdoneチャネルにまとめて、
まとめているチャネルのうちのどれか1つのチャネルが閉じられたら、 まとめたちゃねるも閉じられるようにしたい" • <-or( done1, done2, done3, ) • 再帰処理で実装されており、 コードを読んでいると混乱してしまったので、図にしてみました。
len(channels) == 0 の場合 返り値は nil 返り値は channels[0] len(channels) ==
1 の場合
len(channels) == 2 の場合
orDone switch { case <-channel[0]: case <-channel[1]: } ゴルーチン deferでclose
返り値 = <-chan interface{}
orDone switch { case <-channel[0]: case <-channel[1]: } ゴルーチン deferでclose
返り値 = <-chan interface{} channel[0] or channel[1]の ブロックが解除されたら ゴルーチンが終了する。 その時のdeferでorDoneがcloseされる。
len(channels) == 3 の場合
orDone switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone: } ゴルーチン deferでclose 返り値 = <-chan interface{} チャネルの数が変わっただけで、 len(channels) == 2 の時とほぼ同じ
orDone switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone: } ゴルーチン deferでclose 返り値 = <-chan interface{} 最後のcaseは再帰呼び出しの返り値。 case <-or(append(channels[3:], orDone)): len(channels) == 3の場合、 orDoneが再帰呼び出しの返り値になる。
len(channels) == 4 の場合
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 deferで close 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 deferで close 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close ↑再帰呼び出しでできたやつ orDone2 := or(append(channels[3:], orDone1))
orDone1 switch { … } ゴルーチン1 deferで close 返り値 =
<-chan interface{} switch { … } ゴルーチン2 orDone2 deferで close <-chan interface{} switch { … } ゴルーチン3 orDone3 deferで close <-chan interface{} ・ ・ ・ channelが3つにつき、 1ゴルーチンずつ増えていく
len(channels) == 4 の場合 で動作をみる
パターン1 channel[3]がclose
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 deferで close 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close パターン1 channel[3]がcloseされた場合 switchを抜け、 ゴルーチン2が終了する
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 deferで close 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close パターン1 channel[3]がcloseされた場合 switchΛൈ͚ͯ ऴྃ ゴルーチン終了時の deferでorDone2をclose
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 deferで close 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close パターン1 channel[3]がcloseされた場合 switchΛൈ͚ͯ ऴྃ orDone2をcloseしたので、 switchを抜け、 ゴルーチン1が終了。 closed
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 deferで close 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close パターン1 channel[3]がcloseされた場合 switchΛൈ͚ͯ ऴྃ closed switchΛൈ͚ͯ ऴྃ deferで close ゴルーチン終了時の deferでorDone1をclose
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 deferで close 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close パターン1 channel[3]がcloseされた場合 switchΛൈ͚ͯ ऴྃ closed switchΛൈ͚ͯ ऴྃ deferで close closed ✅ Done
パターン2 channel[0]~channel[2]のどれかがclose
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 deferで close 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close パターン2 channel[0] ~ channel[2] のどれかがcloseされた場合 switchを抜け、 ゴルーチン1が終了する
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 deferで close 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close switchΛൈ͚ͯ ऴྃ deferで close ゴルーチン終了時の deferでorDone1をclose パターン2 channel[0] ~ channel[2] のどれかがcloseされた場合
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 deferで close 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close switchΛൈ͚ͯ ऴྃ 再帰呼び出し時に渡した orDone1がcloseしたので、 switchを抜け、 ゴルーチン2も終了する closed パターン2 channel[0] ~ channel[2] のどれかがcloseされた場合 ※再帰呼び出し時に呼び出し側のorDone(例のorDone1)を渡すのは、 子ゴルーチン(例のゴルーチン2)をcloseするため
orDone1 switch { case <-channel[0]: case <-channel[1]: case <-channel[2]: case
<-orDone2: } ゴルーチン1 返り値 = <-chan interface{} switch { case <-channel[3]: case <-orDone1: } ゴルーチン2 orDone2 deferで close switchΛൈ͚ͯ ऴྃ switchΛൈ͚ͯ ऴྃ closed deferで close ✅ Done パターン2 channel[0] ~ channel[2] のどれかがcloseされた場合
͓ΘΓ