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
range over funcのエラー処理
Search
MakKi
June 07, 2024
1
1.6k
range over funcのエラー処理
(Unofficial)Go Conference 2024 Pre Party
MakKi
June 07, 2024
Tweet
Share
More Decks by MakKi
See All by MakKi
眼鏡と視力についての誤解を解く
makki_d
0
100
標準ライブラリの動向とイテレータのパフォーマンス
makki_d
3
630
GoとテストとインプロセスDB
makki_d
3
550
君は古の言語M4を知っているか (LT)
makki_d
0
370
型パラメータが使えるようになったのでLINQを実装してみた
makki_d
2
1.4k
mallocしただけでメモリが確保できるって本当ですか?
makki_d
0
210
ホットリロードツールの作り方
makki_d
0
1.1k
JavaプログラムをGoに移植するためのテクニック――継承と例外
makki_d
1
1.7k
JavaプログラムをGoに移植するためのテクニック――継承と例外
makki_d
4
4.2k
Featured
See All Featured
Learning to Love Humans: Emotional Interface Design
aarron
273
40k
Evolution of real-time – Irina Nazarova, EuRuKo, 2024
irinanazarova
6
580
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
Adopting Sorbet at Scale
ufuk
75
9.2k
BBQ
matthewcrist
87
9.5k
Code Review Best Practice
trishagee
67
18k
Documentation Writing (for coders)
carmenintech
68
4.6k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Making Projects Easy
brettharned
116
6k
A designer walks into a library…
pauljervisheath
205
24k
Into the Great Unknown - MozCon
thekraken
35
1.6k
For a Future-Friendly Web
brad_frost
176
9.6k
Transcript
range over funcの エラー処理 Go Conference 2024 Pre Party
自己紹介 • MakKi (牧内 大輔) ◦ • KLab株式会社 ◦
オンライン対戦の通信基盤を Goで実装 ◦ github.com/KLab/wsnet2 • 過去の発表 ◦ Goとテストとインプロセス DB ◦ 型パラメータが使えるようになったので LINQを実装してみた ◦ ホットリロードツールの作り方 ◦ … makiuchi-d @makki_d
range over funcとは • Go 1.22 で GOEXPERIMENT入り • for文のrangeに関数を渡せる
◦ func(yield func() bool) ◦ func(yield func(V) bool) ◦ func(yield func(K, V) bool) • yieldした回数だけループが回る ◦ breakするとyieldがfalse ▪ それ以降yieldするとpanic func Three(yield func(int) bool) { if !yield(1) { return } if !yield(2) { return } if !yield(3) { return } } func main() { for n := range Three { fmt.Println(n) } // Output: // 1 // 2 // 3 } https://go.dev/play/p/HguOV9bxf59
関数内でエラー発生 • 呼び出し側(forループ)に errorの値をどうにかして伝えたい • yieldを呼ぶか終了するかしかできない ◦ yield: errorを渡せない ◦
終了: 正常終了と見分けがつかない いまいちな方法〜いいかんじの方法を 4パターン考えてきました func Three(yield func(int) bool) { if !yield(1) { return } err := fmt.Errorf("Error!") } func main() { for n := range Three { fmt.Println(n) } } どうやって伝える?
1. panicする? • forループ側にpanicが伝搬 ◦ recoverすればエラーを取り出せる • 利用者にrecoverさせるのは不親切 func Three(yield
func(int) bool) { if !yield(1) { return } err := fmt.Errorf("Error!") panic(err) } func main() { var err error func() { defer func() { err, _ = recover().(error) }() for n := range Three { fmt.Println(n) } }() if err != nil { fmt.Println(err) } } https://go.dev/play/p/7h-IXsacSb1
2. 受け取り用ポインタ? • error型変数を用意 • errorポインタを受け取り、関数を返す ◦ ポインタの先にerrorを設定して終了する関数 • ループを抜けてからnullチェック
• 実装が複雑 func Three(ep *error) func(func(int) bool) { return func(yield func(int) bool) { if !yield(1) { return } err := fmt.Errorf("Error!") *ep = err } } func main() { var err error for n := range Three(&err) { fmt.Println(n) } if err != nil { fmt.Println(err) } } https://go.dev/play/p/B-fSKCH88AW
3. structに詰めてyield? • 値とerrorをまとめたstructを定義 • そのstructに詰めてyieldに渡す • ループ内でstructの中のerrorをチェック • structの定義が必要
• 毎回詰めたり取り出したり面倒 type ValErr struct { Val int Err error } func Three(yield func(ValErr) bool) { if !yield(ValErr{1, nil}) { return } err := fmt.Errorf("Error!") yield(ValErr{0, err}) } func main() { for ev := range Three { if ev.Err != nil { fmt.Println(ev.Err) break } fmt.Println(ev.Val) } } https://go.dev/play/p/ff0FTnCnfj7
4. 2値のyield! • yield func(K, V) bool • K, Vともにどんな型でもOK
◦ mapのようなcomparable制約はない • 値とerrorをyieldに渡す ◦ for文側で値とerrorを受け取れる • Goとしてよく見る形 • 実装もシンプル ◦ ただしKey-Valueを返すときはKをstructに…… func Three(yield func(int, error) bool) { if !yield(1, nil) { return } err := fmt.Errorf("Error!") yield(0, err) } func main() { for n, err := range Three { if err != nil { fmt.Println(err) break } fmt.Println(n) } } https://go.dev/play/p/0VNRQSv7ELe
まとめ range for funcでエラーを伝えたいときは func(yield func(V, error) bool) の形で関数を実装すると綺麗!
宣伝 技術書典16 KLab Tech Book Vol.13 電子版0円(電子+紙 500円) 既刊もよろしく