Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Go言語による並行処理「4.4 orチャネル」の図
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
Hiroyuki ANAI
October 05, 2021
Technology
480
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Go言語による並行処理「4.4 orチャネル」の図
コードを読んでいて混乱したので図にしました。
Hiroyuki ANAI
October 05, 2021
More Decks by Hiroyuki ANAI
See All by Hiroyuki ANAI
書き換えて学ぶTemporal #fukts
pirosikick
2
420
fukuoka.ts #3 社内でESLintの共通設定を配りたい2025年春版
pirosikick
3
490
compilerOptions、全部読んだ
pirosikick
1
300
Step Functionsの設計時に知っておいたほうがいいかもしれないこと
pirosikick
0
530
サイボウズWebフロントエンド脱レガシーの今までとこれから
pirosikick
6
17k
@cybozu/eslint-configから学ぶ、全社共通ESLint configの運用
pirosikick
4
1.9k
Web Share Target API #w3fukuoka
pirosikick
0
740
Google I/O '19のWebをまとめる会
pirosikick
2
890
PuppeteerでいらないCSSを消す
pirosikick
23
29k
Other Decks in Technology
See All in Technology
歴史から理解するクラウドインフラのしくみ
kizawa2020
1
200
オートロックマンションなのに、各部屋は施錠なし!? 攻撃者が組織内ネットワークで大暴れする理由 / The Front Door Is Locked, but the Rooms Are Wide Open: Why Attackers Move Freely Inside Enterprise Networks
nttcom
0
730
MIRU 2026 チュートリアル
keisuke198619
0
430
Claude Code並行開発環境の ムダ‧ムラ‧ムリを見直した話
muranakaaa
1
390
20260608_Codexの可能性_ノンプログラマー向け_大城追記
doradora09
PRO
0
720
テックカンファレンス三大ステークホルダーの文化人類学 ─ 違いを認め合う関係性作り
bash0c7
5
1.5k
NetBoxを利用した作業効率化の試み_NetDevNight4
tnoha
0
430
Data Hubグループ 紹介資料
sansan33
PRO
0
3.1k
大 AI 時代におけるC# の事情 ~ぶっちゃけトークを交えながら~
nenonaninu
1
620
Atlassian Cloudサポート業務でのAIエージェント活用事例
smt7174
0
230
Webの技術とガジェットで子どもも大人も楽しめるワクワク体験を提供する / Qiita Tech Festa Day 2026
you
PRO
1
330
【5分でわかる】セーフィー エンジニア向け会社紹介
safie_recruit
0
53k
Featured
See All Featured
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
3k
Music & Morning Musume
bryan
47
7.3k
Into the Great Unknown - MozCon
thekraken
41
2.6k
Design in an AI World
tapps
1
270
Tell your own story through comics
letsgokoyo
1
1k
Building Experiences: Design Systems, User Experience, and Full Site Editing
marktimemedia
0
560
Redefining SEO in the New Era of Traffic Generation
szymonslowik
1
370
Building a Scalable Design System with Sketch
lauravandoore
463
34k
Building Flexible Design Systems
yeseniaperezcruz
330
40k
How STYLIGHT went responsive
nonsquared
100
6.2k
[RailsConf 2023] Rails as a piece of cake
palkan
59
6.8k
From Legacy to Launchpad: Building Startup-Ready Communities
dugsong
0
280
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された場合
͓ΘΓ