Submit Search
Upload
Go conference 2021 autumn
•
Download as PPTX, PDF
•
2 likes
•
1,663 views
M
masahiko ito
Follow
Go Conference 2021の発表資料です
Read less
Read more
Internet
Report
Share
Report
Share
1 of 63
Download now
Recommended
Pythonの会社を 9年間経営してきて分かったこと
Pythonの会社を 9年間経営してきて分かったこと
Haruo Sato
CoderDojo ひばりヶ丘の取り組み
CoderDojo ひばりヶ丘の取り組み
Masao Niizuma
Tqrk02 bdd tatssato
Tqrk02 bdd tatssato
Tatsuya Sato
Unityアセットの FairyGUI を使って、一見格好良さそうなGUIを作ろうとしてハマる話
Unityアセットの FairyGUI を使って、一見格好良さそうなGUIを作ろうとしてハマる話
You&I
研修資料
研修資料
Yuta Tonegawa
利根川講演@長野塩尻20170120
利根川講演@長野塩尻20170120
Yuta Tonegawa
小学校段階における論理的思考力や創造性、問題解決能力等の育成とプログラミング教育に関する有識者会議(第1回) みんなのコード 発表資料
小学校段階における論理的思考力や創造性、問題解決能力等の育成とプログラミング教育に関する有識者会議(第1回) みんなのコード 発表資料
Yuta Tonegawa
PyCon JP 2015 keynote
PyCon JP 2015 keynote
Haruo Sato
Recommended
Pythonの会社を 9年間経営してきて分かったこと
Pythonの会社を 9年間経営してきて分かったこと
Haruo Sato
CoderDojo ひばりヶ丘の取り組み
CoderDojo ひばりヶ丘の取り組み
Masao Niizuma
Tqrk02 bdd tatssato
Tqrk02 bdd tatssato
Tatsuya Sato
Unityアセットの FairyGUI を使って、一見格好良さそうなGUIを作ろうとしてハマる話
Unityアセットの FairyGUI を使って、一見格好良さそうなGUIを作ろうとしてハマる話
You&I
研修資料
研修資料
Yuta Tonegawa
利根川講演@長野塩尻20170120
利根川講演@長野塩尻20170120
Yuta Tonegawa
小学校段階における論理的思考力や創造性、問題解決能力等の育成とプログラミング教育に関する有識者会議(第1回) みんなのコード 発表資料
小学校段階における論理的思考力や創造性、問題解決能力等の育成とプログラミング教育に関する有識者会議(第1回) みんなのコード 発表資料
Yuta Tonegawa
PyCon JP 2015 keynote
PyCon JP 2015 keynote
Haruo Sato
[クリエイティブハント2018]LT 道場破りしたらできちゃった/// #ゴーハント
[クリエイティブハント2018]LT 道場破りしたらできちゃった/// #ゴーハント
Hiroyuki Ishikawa
利根川講演@北海道20170113
利根川講演@北海道20170113
Yuta Tonegawa
Pythonの10年と今、これから
Pythonの10年と今、これから
Haruo Sato
Hour of-code-2016冬-シンポジウム
Hour of-code-2016冬-シンポジウム
Yuta Tonegawa
新卒がモンストとファイトリーグリーグ開発で行ったこと
新卒がモンストとファイトリーグリーグ開発で行ったこと
hogehoge14
プレゼンの技術
プレゼンの技術
心 谷本
Hello Engineer World! 新人リケジョの1年
Hello Engineer World! 新人リケジョの1年
Satoko Shiroi
プログラミング有識者会議を読み解く
プログラミング有識者会議を読み解く
Yuta Tonegawa
プレゼンの技術 1 考え方
プレゼンの技術 1 考え方
心 谷本
20180826 learn languages 2018 in odc
20180826 learn languages 2018 in odc
TakayukiTakahashi4
CTOやフリーランスのキャリアについて
CTOやフリーランスのキャリアについて
Yusuke Kon
CNCFアップデート情報~2018年のCNCFを振り返る
CNCFアップデート情報~2018年のCNCFを振り返る
Masahito Zembutsu
オンラインPython学習サービスPyQの価格決め
オンラインPython学習サービスPyQの価格決め
Haruo Sato
プログラミング教育シンポジウム@札幌 資料
プログラミング教育シンポジウム@札幌 資料
Yuta Tonegawa
Triz20200617_Univ_Tokyo
Triz20200617_Univ_Tokyo
芳徳 高木
クラッシュフィーバーのシステム構成
クラッシュフィーバーのシステム構成
Tomotsune Murata
かなしき だるやなぎちゃん ~海老を獲りに行く話~
かなしき だるやなぎちゃん ~海老を獲りに行く話~
You&I
プログラミング教育の基礎知識
プログラミング教育の基礎知識
Masahito Zembutsu
Hour of code教材解説@福井
Hour of code教材解説@福井
Yuta Tonegawa
そうだ、Goを始めよう
そうだ、Goを始めよう
Takuya Ueda
ここがスゴい(変だ)よ!Git lab!
ここがスゴい(変だ)よ!Git lab!
Naoharu Sasaki
WebAssembly with Go
WebAssembly with Go
Takuya Ueda
More Related Content
What's hot
[クリエイティブハント2018]LT 道場破りしたらできちゃった/// #ゴーハント
[クリエイティブハント2018]LT 道場破りしたらできちゃった/// #ゴーハント
Hiroyuki Ishikawa
利根川講演@北海道20170113
利根川講演@北海道20170113
Yuta Tonegawa
Pythonの10年と今、これから
Pythonの10年と今、これから
Haruo Sato
Hour of-code-2016冬-シンポジウム
Hour of-code-2016冬-シンポジウム
Yuta Tonegawa
新卒がモンストとファイトリーグリーグ開発で行ったこと
新卒がモンストとファイトリーグリーグ開発で行ったこと
hogehoge14
プレゼンの技術
プレゼンの技術
心 谷本
Hello Engineer World! 新人リケジョの1年
Hello Engineer World! 新人リケジョの1年
Satoko Shiroi
プログラミング有識者会議を読み解く
プログラミング有識者会議を読み解く
Yuta Tonegawa
プレゼンの技術 1 考え方
プレゼンの技術 1 考え方
心 谷本
20180826 learn languages 2018 in odc
20180826 learn languages 2018 in odc
TakayukiTakahashi4
CTOやフリーランスのキャリアについて
CTOやフリーランスのキャリアについて
Yusuke Kon
CNCFアップデート情報~2018年のCNCFを振り返る
CNCFアップデート情報~2018年のCNCFを振り返る
Masahito Zembutsu
オンラインPython学習サービスPyQの価格決め
オンラインPython学習サービスPyQの価格決め
Haruo Sato
プログラミング教育シンポジウム@札幌 資料
プログラミング教育シンポジウム@札幌 資料
Yuta Tonegawa
Triz20200617_Univ_Tokyo
Triz20200617_Univ_Tokyo
芳徳 高木
クラッシュフィーバーのシステム構成
クラッシュフィーバーのシステム構成
Tomotsune Murata
かなしき だるやなぎちゃん ~海老を獲りに行く話~
かなしき だるやなぎちゃん ~海老を獲りに行く話~
You&I
プログラミング教育の基礎知識
プログラミング教育の基礎知識
Masahito Zembutsu
Hour of code教材解説@福井
Hour of code教材解説@福井
Yuta Tonegawa
What's hot
(19)
[クリエイティブハント2018]LT 道場破りしたらできちゃった/// #ゴーハント
[クリエイティブハント2018]LT 道場破りしたらできちゃった/// #ゴーハント
利根川講演@北海道20170113
利根川講演@北海道20170113
Pythonの10年と今、これから
Pythonの10年と今、これから
Hour of-code-2016冬-シンポジウム
Hour of-code-2016冬-シンポジウム
新卒がモンストとファイトリーグリーグ開発で行ったこと
新卒がモンストとファイトリーグリーグ開発で行ったこと
プレゼンの技術
プレゼンの技術
Hello Engineer World! 新人リケジョの1年
Hello Engineer World! 新人リケジョの1年
プログラミング有識者会議を読み解く
プログラミング有識者会議を読み解く
プレゼンの技術 1 考え方
プレゼンの技術 1 考え方
20180826 learn languages 2018 in odc
20180826 learn languages 2018 in odc
CTOやフリーランスのキャリアについて
CTOやフリーランスのキャリアについて
CNCFアップデート情報~2018年のCNCFを振り返る
CNCFアップデート情報~2018年のCNCFを振り返る
オンラインPython学習サービスPyQの価格決め
オンラインPython学習サービスPyQの価格決め
プログラミング教育シンポジウム@札幌 資料
プログラミング教育シンポジウム@札幌 資料
Triz20200617_Univ_Tokyo
Triz20200617_Univ_Tokyo
クラッシュフィーバーのシステム構成
クラッシュフィーバーのシステム構成
かなしき だるやなぎちゃん ~海老を獲りに行く話~
かなしき だるやなぎちゃん ~海老を獲りに行く話~
プログラミング教育の基礎知識
プログラミング教育の基礎知識
Hour of code教材解説@福井
Hour of code教材解説@福井
Similar to Go conference 2021 autumn
そうだ、Goを始めよう
そうだ、Goを始めよう
Takuya Ueda
ここがスゴい(変だ)よ!Git lab!
ここがスゴい(変だ)よ!Git lab!
Naoharu Sasaki
WebAssembly with Go
WebAssembly with Go
Takuya Ueda
タスク管理ツールJootoによるゲーム開発実例について
タスク管理ツールJootoによるゲーム開発実例について
yusuke hara
確定申告ってなんでやるの?.pdf
確定申告ってなんでやるの?.pdf
ssusera9322b
[XP祭り2020]組織にはびこるなんちゃってスクラムからの脱却を目指して
[XP祭り2020]組織にはびこるなんちゃってスクラムからの脱却を目指して
グロースエクスパートナーズ株式会社/Growth xPartners Incorporated.
エンジニアになり1ヶ月が経って!
エンジニアになり1ヶ月が経って!
ssuserccd9f1
第7回SIA研究会(例会)プレゼン資料 油野様
第7回SIA研究会(例会)プレゼン資料 油野様
Tae Yoshida
agatsuma.survive#5
agatsuma.survive#5
Yoshiaki Sugimoto
採用ピッチ資料_2023
採用ピッチ資料_2023
Flyke1
Go初心者向けハンズオン コマンドラインツールを作ろう
Go初心者向けハンズオン コマンドラインツールを作ろう
Takuya Ueda
RTC2023_ChatGPT_YukiTsukamae.pdf
RTC2023_ChatGPT_YukiTsukamae.pdf
hossenkamal2
RTC2023_ChatGPT_YukiTsukamae.pptx
RTC2023_ChatGPT_YukiTsukamae.pptx
hossenkamal2
一生、エンジニアであり続けるために必要なこと「負けてからのエンジニアライフ」
一生、エンジニアであり続けるために必要なこと「負けてからのエンジニアライフ」
雄哉 吉田
メルカリ カウルのマスタデータの更新
メルカリ カウルのマスタデータの更新
Takuya Ueda
Goにおけるバージョン管理の必要性 − vgoについて −
Goにおけるバージョン管理の必要性 − vgoについて −
Takuya Ueda
enPiT修了生は、大学卒業後の一歩をどう選んだか
enPiT修了生は、大学卒業後の一歩をどう選んだか
Shizuru Kosuge
アンラーニング
アンラーニング
Yoshiki Shibukawa
Contribute to terraform-provider-aws
Contribute to terraform-provider-aws
健太郎 平松
10数年運用されているシステムの紐解き方
10数年運用されているシステムの紐解き方
amano shohei
Similar to Go conference 2021 autumn
(20)
そうだ、Goを始めよう
そうだ、Goを始めよう
ここがスゴい(変だ)よ!Git lab!
ここがスゴい(変だ)よ!Git lab!
WebAssembly with Go
WebAssembly with Go
タスク管理ツールJootoによるゲーム開発実例について
タスク管理ツールJootoによるゲーム開発実例について
確定申告ってなんでやるの?.pdf
確定申告ってなんでやるの?.pdf
[XP祭り2020]組織にはびこるなんちゃってスクラムからの脱却を目指して
[XP祭り2020]組織にはびこるなんちゃってスクラムからの脱却を目指して
エンジニアになり1ヶ月が経って!
エンジニアになり1ヶ月が経って!
第7回SIA研究会(例会)プレゼン資料 油野様
第7回SIA研究会(例会)プレゼン資料 油野様
agatsuma.survive#5
agatsuma.survive#5
採用ピッチ資料_2023
採用ピッチ資料_2023
Go初心者向けハンズオン コマンドラインツールを作ろう
Go初心者向けハンズオン コマンドラインツールを作ろう
RTC2023_ChatGPT_YukiTsukamae.pdf
RTC2023_ChatGPT_YukiTsukamae.pdf
RTC2023_ChatGPT_YukiTsukamae.pptx
RTC2023_ChatGPT_YukiTsukamae.pptx
一生、エンジニアであり続けるために必要なこと「負けてからのエンジニアライフ」
一生、エンジニアであり続けるために必要なこと「負けてからのエンジニアライフ」
メルカリ カウルのマスタデータの更新
メルカリ カウルのマスタデータの更新
Goにおけるバージョン管理の必要性 − vgoについて −
Goにおけるバージョン管理の必要性 − vgoについて −
enPiT修了生は、大学卒業後の一歩をどう選んだか
enPiT修了生は、大学卒業後の一歩をどう選んだか
アンラーニング
アンラーニング
Contribute to terraform-provider-aws
Contribute to terraform-provider-aws
10数年運用されているシステムの紐解き方
10数年運用されているシステムの紐解き方
Recently uploaded
動的 & 非同期コンポーネント / Dynamic & Async Components
動的 & 非同期コンポーネント / Dynamic & Async Components
okitamasashi
Windows 10、Windows 11の付箋を簡単に復元する6つの方法|データ復元
Windows 10、Windows 11の付箋を簡単に復元する6つの方法|データ復元
ivanwang53
ダウンロードがダウンロード(Downloads)フォルダに表示されない」問題の対処法
ダウンロードがダウンロード(Downloads)フォルダに表示されない」問題の対処法
ivanwang53
Windows Defenderのフル・クイック・カスタム・オフラインスキャンを実行する方法.docx
Windows Defenderのフル・クイック・カスタム・オフラインスキャンを実行する方法.docx
ivanwang53
あらゆる通信環境で切れない「ネットモーション」のモバイルアクセス [NetMotion]
あらゆる通信環境で切れない「ネットモーション」のモバイルアクセス [NetMotion]
Taka Narita
Windowsアップデート後の黒い画面を修正する方法|データ復元|ブラックスクリーン
Windowsアップデート後の黒い画面を修正する方法|データ復元|ブラックスクリーン
ivanwang53
Recently uploaded
(6)
動的 & 非同期コンポーネント / Dynamic & Async Components
動的 & 非同期コンポーネント / Dynamic & Async Components
Windows 10、Windows 11の付箋を簡単に復元する6つの方法|データ復元
Windows 10、Windows 11の付箋を簡単に復元する6つの方法|データ復元
ダウンロードがダウンロード(Downloads)フォルダに表示されない」問題の対処法
ダウンロードがダウンロード(Downloads)フォルダに表示されない」問題の対処法
Windows Defenderのフル・クイック・カスタム・オフラインスキャンを実行する方法.docx
Windows Defenderのフル・クイック・カスタム・オフラインスキャンを実行する方法.docx
あらゆる通信環境で切れない「ネットモーション」のモバイルアクセス [NetMotion]
あらゆる通信環境で切れない「ネットモーション」のモバイルアクセス [NetMotion]
Windowsアップデート後の黒い画面を修正する方法|データ復元|ブラックスクリーン
Windowsアップデート後の黒い画面を修正する方法|データ復元|ブラックスクリーン
Go conference 2021 autumn
1.
Go Contextを完全に理解する 伊藤 真彦 The
Gopher character is based on the Go mascot designed by Renée French
2.
伊藤真彦 Masahiko Ito フューチャー株式会社
TIG DXチーム所属 担当領域: コンサルタントとしてなんでもやっています 趣味: ギター 資格: @it_guitar 自己紹介
3.
フューチャーは ITコンサルティングを中心に開発、保守までを 一気通貫の体制で行う会社です。 自己紹介
4.
自己紹介 発表のモチベーション ● よくわからないまま使っている機能があるので理解したかった ○ 例:
ポインタ、2020年のGoアドベントカレンダーのネタにした ● contextが期待通りの状態になっているかデバッグするのに苦労した、 発表を通してしっかり理解し、また理解できるコンテンツを作りたい ● contextは少ない行でGoのテクニックをたくさん使っている 実装を深堀すると学びになる
5.
Contextとは
6.
Contextとは contextはAPIの境界を越えて、プロセス間で、期限、キャンセルシグナル、 およびその他のリクエストスコープの値を伝達します 採用したライブラリがContextを渡してくれる→後続処理に渡す これだけで複雑な並行処理であってもタイムアウトやキャンセルの制御が可能 https://pkg.go.dev/context
7.
Contextとは 例: AWS SDKのLambdaハンドラ→Amazon
Dynamo DB SDKを利用したDBリクエスト
8.
Contextとは もちろん任意の実装も可能 例: 5秒間処理を繰り返す https://play.golang.org/p/HBDan3ykITr
9.
Contextとは 例: Go 1.16のsignal.NotifyContext()を用いたgracefulシャットダウン 詳しくは https://future-architect.github.io/articles/20210212/
10.
Contextとは zennの記事、出た(無料)
11.
Contextとは タイムライン(言い訳) プロポーザル提出 zenn無料書籍公開 プロポーザル採択 2021/08/03
2021/08/28 2021/09/15
12.
Contextとは 逆に言うと内部実装の理解にフォーカスできます、素晴らしい情報に感謝
13.
Contextの内部実装
14.
Contextの内部実装 Contextは発表段階(2021年10月)で593行で実装されています https://github.com/golang/go/blob/master/ src/context/context.go
15.
Contextの内部実装 Contextはinterfaceです
16.
Contextの内部実装 序盤はコメントが多いので、これだけで154行まで説明が済みます
17.
Contextの内部実装 次にキャンセル、タイムアウト時に所定のメッセージを返すための エラーが定義されています timeOut(), Temporary()は内部では利用されていません netパッケージで提供されているエラーと同じインターフェース仕様を満たすことで 呼び出し元でのリトライ実行の制御などに役立てることができます
18.
Contextの内部実装 参考: netパッケージのError interface https://github.com/golang/go/blob/master/src/net/net.go#L397 使い方イメージ
19.
Contextの内部実装 ContextのベースとなるemptyCtxが定義されています intがベースとなっているのはこの型の値の全てが 異なるアドレスを持つようにするためです Interfaceとしての仕様を満たす関数を備えつつ、 それぞれの型の0値を返します Deadline()で名前付きの戻り値を利用することで、 return一行で 0001-01-01 00:00:00 +0000
UTC, false を返却するのはGoにしては珍しいトリッキーな書き方 String()だけはbackgroundとtodoを区別するための switch文が書かれています
20.
Contextの内部実装 background, todoはvarで定義されています context.TODO()、のような使い方でそれぞれのemptyCtxを取得します backgroundとtodoの違いis 何? 持っている機能としては100%同じ 後続の処理で区別するような記述は一切なし 可読性のために使い分け context.Background() これからデッドラインなどを仕込むための準備とし て呼び出す context.TODO() contextの用途が明確ではない、もしくは必要か明 確に定まっていないときに呼び出す backgroundを使うべき状況でtodoを使っても機能的 には問題ない
21.
Contextの内部実装 > 値の全てが異なるアドレスを持つようにするため 何のことを言っているのかは試してみると理解できます
22.
Contextの内部実装 220行目からキャンセル機能が実装されています 構造体cancelCtxは340行目で定義されています WithCancelで親のContextを与えると、そ れを取り込んだcancelCtxと キャンセルのための関数が取得できます この設計からcontextの親子関係の仕組み が推察できます
23.
Contextの内部実装 245行目で親のキャンセル情報を子に伝播するための実装が行われています contextの中では比較的複雑な実装です 親コンテキストがキャンセル済でない cancelCtxの場合は親コンテキストのキャ ンセルを伝播させる対象を集めるmapに子 コンテキストを詰め込みます
24.
Contextの内部実装 少々難しい処理ですが、parentCancelCtxで親contextの状態、型を確認しながら キャンセル状況を伝播させるか否か整理しています 実装部分のコメントを翻訳 parentCancelCtxは、親の基になる* cancelCtxを返し ます。 これは、parent.Value(&cancelCtxKey)を検索し て見つけることによって行われます。 最も内側の囲んでいる* cancelCtxをチェックし、 parent.Done()はその*
cancelCtxと一致します。 (そうでない場合、* cancelCtx 別の完了チャネルを提供するカスタム実装にラップ されています。その場合、それをバイパスしないで ください。)
25.
Contextの内部実装 312行目で後々の行で利用するremoveChildが実装されています 親contextにcancelCtxが存在する場合、ロックをかけながらchildrenの情報を削除 します、delete()はGoの組み込み関数です
26.
Contextの内部実装 326行目でcancelerが定義されています cacelerの実態はcancelCtxなどcontext自身です
27.
Contextの内部実装 333行目〜closedchanとcancelCtxが定義されています
28.
Contextの内部実装 351行目〜cancelCtxのValue, Done, Errが定義されています
29.
Contextの内部実装 380行目~ String()とそれで用いる関数が定義されています StringはinterfaceとしてのContextに定義されていないため、直接呼び出すことは できません
30.
Contextの内部実装 できない できる
31.
Contextの内部実装 正しい使い方
32.
Contextの内部実装 397行目〜 cancelが実装されています WithCancelで取得できる関数です
33.
Contextの内部実装 425行目〜 WithDeadLineが実装されています DeadLine時刻が既に過ぎているか、親のコンテキス トにより短いデッドラインが存在するか、など保険と なる実装がありますが、 基本的には引数で与えたDeadline時刻をタイマーとし てセットしています
34.
Contextの内部実装 time.AfterFuncの存在は覚えておきたい
35.
Contextの内部実装 465行目にtimerCtxが定義されています cancelCtxがフィールドに埋め込まれており、timerCtxはcancelCtxの拡張であるこ とがわかります
36.
Contextの内部実装 func (t *timerCtx)
Done()のような記述は一切ありませんが、 構造体の埋め込みによりtimerCtxはcancelerのインターフェース仕様を 満たしています
37.
Contextの内部実装 一方cancelは埋め込んだcancelCtxのcancelを呼び出しつつ、 タイマーを掃除するtimerCtx独自のものが実装されています
38.
Contextの内部実装 472行目〜 DeadLine()が実装されています emptyCtxと比較すると0値でない値が取得できていることがわかります cancelCtxは独自のDeadline関数を持たず、埋め込まれた親コンテキストのDeadline を呼んでいます 参考: 今まで出てきたCtx
39.
Contextの内部実装 476行目~ timerCtxのString()が実装されています 参考: 今まで出てきたCtx
40.
Contextの内部実装 496行目〜 WithTimeoutが実装されています WithDeadlineのラッパーであることがわかります
41.
Contextの内部実装 510行目〜 WithValueが定義されています keyもvalueもinterface{}です
42.
Contextの内部実装 valueCtxは親Contextとkey, valを持った比較的シンプルな構造体です
43.
Contextの内部実装 valueCtxも独自のString()関数を持っています stringify は、fmt を使わずに
v を文字列化しよ うと少しだけ試みます。 というのは、 私たちはcontextがunicodeテーブルに依存する 事を望まないからです。 これは*ValueCtx.String()でのみ使用されます 。
44.
Contextの内部実装 fmtパッケージを使うとバイナリサイズに800KBほど影響が及ぶ
45.
Contextの内部実装 ポイント: contextはPrint関数で表示されない情報は持っていない 参考: https://future-architect.github.io/articles/20201112/
46.
Contextの内部実装 クライアントでlambda関数を起動、渡すctxにvalueを詰める AWS Lambdaの上で実行されるコードでcontextを利用 しかしctxに詰めたvalueが取得できない 一度HTTPリクエストを経由する都合上valueは失われる(値の伝達はPayload使え) という結論に至るまでに結構プリントデバッグした プリントデバッグした時点でValueが表示されなかったらValueは存在しない事を知 っておけば自信を持って早期に結論を出せた
47.
Contextの内部実装 valueCtxの目玉機能のValue関数が実装されています 各Context特有の挙動をとりつつ、 emptyCtx以外は後述するvalueを呼び出します 参考: 今まで出てきたCtx
48.
Contextの内部実装 Valueに渡す値は==で一致するものであればなんでも良いですが メモリ効率を考えるとint型の変数のポインタを投げるのが推奨(?) 内部ではそうしているだけですが
49.
Contextの内部実装 ポインタ型を投げなくてももちろん動きます 文字列などでラフに値を取り出したいか keyの重複を考慮せずに済む方が良いかで使い分けできます
50.
Contextの内部実装 最後に内部で呼び出されるvalue関数の実装をもって593行が終了です keyがヒットするかemptyCtxにたどり着くまで 無限に各context型のValueとほぼ同じことをします 再帰関数になりそうでならない実装です
51.
まとめ
52.
まとめ ● interface仕様を満たした4種類の〇〇Ctxが存在する ● これらCtxを親子関係としてネストできる
53.
まとめ 学びになるポイント ● Interfaceの使い方 ● 型アサーションを用いるswitch文の使い方
54.
まとめ 学びになるポイント ● 独自のエラー型の使い方
55.
まとめ 学びになるポイント ● sync.Mutexの使い方
56.
まとめ 学びになるポイント ● channelの使い方
57.
まとめ 学びになるポイント ● sync/atomicの使い方
58.
まとめ 学びになるポイント ● intを拡張した型を利用する
59.
まとめ 学びになるポイント ● 名前付き変数によるreturn文の簡略化
60.
まとめ 学びになるポイント ● 構造体に構造体、インターフェースを埋め込む
61.
まとめ 学びになるポイント ● 順番が重要でない、任意の値が入っているか確認できれば良い コレクションはkeyに使いたい値を詰めたmapにする 改めてpropagateCancel関数と、 それを呼び出している実装を見直すと参考になると思います
62.
まとめ Goはシンプルであれが足りない、とか言うけど 言うほどGoを使いこなしてる?
63.
技術を読む 人・企業を知る 技術を聴く 勉強会に参加する フューチャーの技術ブログ。 業務で利用している幅広い技術について 、最新のトピックを交えて紹介します。 フューチャーの技術者によるポッドキャスト。 技術の深堀りトークやブログ記事の裏に隠され た秘話をお届けします。 フューチャーの人、カルチャー、イベントレ ポートなどを幅広く発信。ありのままのフュ ーチャーをタイムリーに紹介します。 未来報 connpass エンジニアや IT
コンサルタント向けの勉強会 を定期的に開催。フューチャーが業務を通して 得た技術的な知見やナレッジを共有します Future Tech Blog Future Tech Cast https://future-architect.github.io/ https://anchor.fm/futuretechcast https://note.future.co.jp/ https://future.connpass.com/ フューチャーをもっと知るには?
Editor's Notes
自己紹介です。私は伊藤真彦と申します。フューチャー株式会社という会社で、ITコンサルタントとして働いています。担当領域は要件定義から実装まで全てです。今年はAWSの資格を取ることに力を入れていました、気持ちよく自己紹介するために先週11個すべてを取得しました。
会社の説明もさせていただきます。フューチャーはITコンサルティングを中心に、開発、保守までを一気通貫の体制で行う会社です。Go Conferenceのブロンズスポンサーをやっています。本日は私を含め3名の社員が登壇しています。
発表のモチベーションですが、皆さんはGoでいうとポインタやインターフェースなど、熟知しているとはいえないものの使えている機能に心当たりは無いでしょうか。私にとってはContextもそのうちの一つでした、抽象化されたインターフェースがある事は素晴らしい事ですが、そういったものを一度立ち止まって深く理解する機会を設けたいなと思い、発表のテーマに選びました。また、今回の発表はcontextの内部実装を追う事で知らなかった、忘れていた、というGoのテクニックを学べるものになるように意識しています。
それでは、Contextの概要から説明します。
contextはAPIの境界を越えて、プロセス間で、期限、キャンセルシグナル、 およびその他のリクエストスコープの値を伝達します、と公式の説明に記載されています。平たく言うと、採用したライブラリがContextを提供してくれたり、DBクライアントライブラリなどがcontextを受け取る機能を用意している場合があります。 そこでcontextをバケツリレーのように渡していくだけでタイムアウトやキャンセルが適宜制御される、といったものです。
例えば、AWS Lambdaの上で動くコードを書く際に利用するライブラリを利用すると、エントリポイントとなる関数のlambda.Startに渡す任意の実装がcontextを受け取るようになっています。 また、DynamoDBに接続するためのクライアントライブラリはcontextを受け取り、contextに設定されたタイムアウト時間を過ぎるとDBへのアクセスを中断できる関数が存在します。
もちろん任意の実装も可能です、ここで書いている処理は、context.WithTimeout関数で作ったcontextに対して設定した時間、処理を繰り返すコードになっています。 コードを読んでみます、5秒後にタイムアウトする設定をしたcontextの変数を作成して、execute関数に渡しています、execute関数では無限ループを行っていますが、select文でcontextのタイムアウトを監視し、タイムアウトした場合は処理を終了するように実装しています、処理は一秒間待機してExecute Somethingという文字列を吐いているだけですが、実行結果のように5秒間処理を繰り返したあとに停止しています。
より実用的な例として、Go1.16から採用されたsignal.NotifyContext()を用いたgracefulシャットダウンを紹介します。gracefulシャットダウンとはつまりユーザーがプロセスをキルしても安全に停止できる処理ですね。これは渋川さんがフューチャー技術ブログに書いています。
このように、contextには様々な使い方が存在しますが、最近zennにわかりやすい書籍が公開されました。目次の通り、contextがもっている機能とその使い方が説明されています。これを読めば基本的な使い方はマスターできます。
なぜ質の高い情報があるのに発表するのか、という言い訳なんですが、私がcontextをテーマに登壇するプロポーザルを提出してから先ほどの書籍が公開されました。そしてわざわざ撤回するべきかと迷っている間に採択された形です。正直焦りました。
しかし、この本のお陰で私の発表は内部実装にフォーカスしたものにすることができます、ありがとうございます。
というわけで、次のセクションからは内部実装を深堀していきます
Contextは発表段階で593行ですべてが実装されています。 そのくらいの量であれば今日の発表で全部コードリーディングできるだろう、というのが発表の趣旨です
頭からコードを読む前にcontextとは、という話をします contextの実態はinterfaceです、Deadline Done Err Valueの4つのインターフェース使用を満たしたcontext構造体がいくつか存在し、外部からはそれらを抽象化して利用しています
序盤はコメントが多いので、これだけで154行まで説明が済みます
次に、キャンセル、タイムアウト時に所定のメッセージを返すためのエラーが2種類定義されています。Canceldはシンプルなエラーです DeadlineExceededは通常のエラーより拡張された独自のエラー型です、拡張機能として実装されたTimeout, Temporaryは内部では利用されていません これらはnetパッケージで提供されているエラーと同じインターフェース使用を満たすことで、呼び出し元でのリトライ制御に役立てることができます
参考までにnetパッケージのErrorインターフェースを見てみましょう、左上の画像の通り、素朴なerrorに加えtimeout, Temporaryが拡張されたインターフェースが実装されています。このインターフェース仕様を満たす独自の構造体errNetClosingなどがnetパッケージには存在します。context内部の独自エラーはこの作法に則っています。使い方は右側の画像の通り、型アサーションでnet.Errorインターフェースの仕様を満たすかを確認してからTemporaryメソッドを呼び出して、リトライやログレベルの分岐などの制御が行えます。
contextの話に戻りますが、エラーなど定数的な情報の記述が終わったら、最も素朴なemptyCtxが定義されています。emptyCtxはintがベースとなった型です。この型の変数が全て異なるアドレスを持つために、structではなくintから型を定義しているとコメントに書いてあります、詳しくは後で説明します。 emptyCtxはInterface仕様を満たすための関数を備えています。いずれもnilやfalseのような値を返すものが多いです。Deadline関数では、名前付きの戻り値を使う事でreturn文をシンプルに書いたままtime.Timeとboolの0値を返却する、というトリッキーな書き方になっています。この手法を業務で上手く使う人は少ないと思いますので、テクニックとして覚えておきたいですね。Stringだけはbackgroundとtodoを区別するためのswitch文が書かれています。
Background, todoは内部で変数定義されています、この二つのemptyCtxを外部から取得する Background, TODOが定義されています。一見するとbackgroundとtodoはStringメソッドの処理の分岐結果以外に違いがありません。実際持っている機能としては完全に同じで、後続処理でもこの二つを区別していません。コメントを読んでみると、可読性のためにわけられている事がわかります。context.Backgroundは、これから設定を詰めるための初期化のために取得するcontextです。一方todoは用途が明確でない、もしくは必要か明確に定まっていないときに一時的に置いておくものとして呼び出します。意義としての使い分けはされていますが、backgroundを使って欲しいタイミングでtodoを呼び出してもバグが起きることはありません
値のすべてが異なるアドレスを持つ、とはどういう事なのかは、実際に動かしてみるとわかります。intを基にした型とstructを基にした型を用意し、その方の変数を複数作ります。これらは同じ型なので==で比較できますが、intを基にした型は一つ一つの変数を宣言するたびに新しくメモリを確保し、違うアドレスが割り当てられますが、空のstructを基に型を作ると、同じデータが使いまわされ、メモリが節約されます。この挙動の違いがあるため、emptyCtxがstructで作られた場合はbackgroundとtodoを比較するとtrueになります。これを回避するためにemptyCtxはintを拡張したものとして作られています。
emptyCtxは以上です、続いてcancelCtxの実装が始まります、cancelCtxはその名の通り処理のキャンセル機能を作るうえで役立つ実装が組み込まれたcontextです、WithCancel関数でcancelCtxと、それをキャンセルするための関数を取得できます。emptyCtx以外はWith~の関数で呼び出すときに親のコンテキストを渡して、親子関係をネストする仕組みが作られています。
245行目あたりから、親子関係としてネストしているコンテキストのキャンセル情報を伝播させるための関数が実装されています。言葉にするとシンプルですがcontextパッケージの中では読み解くのが難しい部類です。
propagateCancel内部で呼び出されているparentCancelCtxで、親コンテキストの状態、型を確認しながら、キャンセル状況を伝播させるための関係性を整理しています、コメントを読んでみても割と内容が伝わりづらいです。
314行目でremoveChildが実装されています、その名の通り、cancelCtxに登録されたchildrenを掃除するための処理です
326行目でcanceleインターフェースが定義されています、これはcancelCtxと、このあと紹介するtimerCtxがこの仕様を満たします。
333行目でclosedchanとcancelCtxが定義されています、closedchanはその名の通りinitで即閉じられるチャネルです。 cancelCtxがキャンセルされているか否かはチャンネルの状態で判断しています。
351行目から、Value Done Errが定義され、contextのインターフェース仕様を満たしています。cancelCtxは並行処理で動作する事を見越して作られているので、読み込むと並行処理の勉強になります。
380行目~ String()とそれで用いる関数が定義されています StringはinterfaceとしてのContextに定義されていないため、直接呼び出すことはできません
試してみると画像のようになります、画像右のようにstringerインターフェースを定義して型アサーションする事で無理やり呼び出すことは可能です。
ややこしい事をしなくても、fmtパッケージのPrint関数に渡すことで同じことができます。
397行目から、cancelが実装されています。これはcontext.WithCance関数lで取得できるキャンセル機能です。これを実行するとcancelContextの持っているチャンネルがcloseされます。同時に親子関係を参照し、キャンセル状況を伝播させるべきcontextもキャンセルします。
cancelCtxについては以上です。425行目から、WithDeadLine関数が実装されています。この関数には親のcontextとデッドラインとなる時刻を引数で渡します。親のコンテキストが既にタイムアウト済であったり、与えたデッドラインが過去の時間だった場合の保険も実装されていますが、デッドラインの時刻でキャンセルが呼び出されるように予約されたtimerCtxと、それを任意のタイミングでキャンセルする関数が返却されます。
ここで使われているtime.AfterFuncは、処理を遅延実行させることが簡単に行える便利な機能です、覚えておくと予約実行機能を実装したい時に役に立ちます。
465行目にtimerCtxが定義されています。cancelCtxがフィールドに埋め込まれており、timerCtxはcancelCtxの拡張であることがわかります。cancelCtxに、キャンセルの予約実行機能と、デッドライン時刻の返却機能をもたせたものがtimerCtxという事になります。
func (t *timerCtx) Done()のような記述は一切ありませんが、構造体の埋め込みによりtimerCtxはcancelerのインターフェース仕様を満たしています,Goはこのように埋め込んだ構造体、インターフェースが持っている関数を直接呼び出すことができます。
一方cancelは埋め込んだcancelCtxのcancelを呼び出しつつ、 タイマーを掃除するtimerCtx独自のものが実装されています
472行目〜 DeadLine()が実装されています emptyCtxと比較すると0値でない値が取得できていることがわかります cancelCtxは独自のDeadline関数を持たず、埋め込まれた親コンテキストのDeadlineを呼んでいます
476行目から、timerCtxのString関数が実装されています。思ったより素朴に文字列が+演算子で結合されています。
496行目からWithTimeout関数が実装されています。実装を見てみると、WithDeadLineのラッパー関数である事がわかります。
timerCtxについては以上です、続いて最後のcontextであるvalueCtxの説明に入ります。510行目からWithValue関数が定義されています。親コンテキストと、key, valueを受け取り、任意の値をもったvalueCtxを返却します。
valueCtxは親Contextとkey, valを持った比較的シンプルな構造体です、keyもvalも空のinterfaceです
valueCtxも独自のString()関数を持っています 敢えてfmtパッケージには依存せずに独自のstringify関数をもっています、unicode tablesに依存したくないとコメントがありますが、話が高度すぎて意図を完璧に理解できているか自信がありませんが。
実際にシンプルなコードで試してみましたが、fmtパッケージをインポートするとビルド結果が800KBほど大きくなりました
ともかくこれで全てのcontextのString関数を読み込みました、ここで大事な事は、contextはプリントデバッグすると持っている情報を全て吐き出すという事です。一緒に働いている辻さんがブログにしてくれたのですが、GoのコードでLambdaを呼び出すときに、Contextに詰めた値を取り出そうとして取り出せず混乱した経験があります
どういう事かというと、クライアント側でAWS Lambdaを起動するために呼び出す関数にcontextを渡すことができるのですが、そのcontextに詰めたValueがLambda上で動くコードでは消滅するのが仕様なのか否かを判断するのにそこそこ時間を使って調査したことがありました。 情報がプリントデバッグして無いなら無いんだ、と自信をもって判断して良い、という事が発表から伝われば幸いです。
さてcontextの実装の話に戻ります、562行目から、valueCtxの目玉機能のValue関数が実装されています、keyが一致したらvalを返すという、シンプルな実装ですね
Valueに渡す値は==で一致するものであればなんでも良いですがcontextパッケージの内部実装ではint型の変数を○○keyの名称で用意して、そのポインタ型を利用する使い方が良く使われています。おそらくメモリ効率を考えるとこの手法が一番スマートです。
ポインタ型を投げなくてももちろん動きます。文字列などでラフに値を取り出したいかkeyの重複を考慮せずに済む方が良いかで使い分けできます
最後に内部で呼び出されるvalue関数の実装をもって593行が終了です、keyがヒットするかemptyCtxにたどり着くまで無限に各context型のValueとほぼ同じことをします 再帰関数になりそうでならない実装です
さて、これでcontextのコードリーディングは終了です、駆け足でしたが、これを読み込むことで何が勉強になるかを整理してみます。
Download now