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
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
MakKi
June 07, 2024
1.8k
1
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
range over funcのエラー処理
(Unofficial)Go Conference 2024 Pre Party
MakKi
June 07, 2024
More Decks by MakKi
See All by MakKi
テストだけじゃない!インプロセスDBで生まれるGoらしさ
makki_d
0
47
テストだけじゃない!インプロセスDBで生まれるGoらしさ
makki_d
0
60
SQLだけでマイグレーションしたい!
makki_d
0
1.4k
Recap: An Operating System in Go
makki_d
2
170
XSLTで作るBrainfuck処理系
makki_d
0
390
眼鏡と視力についての誤解を解く
makki_d
0
230
標準ライブラリの動向とイテレータのパフォーマンス
makki_d
3
780
GoとテストとインプロセスDB
makki_d
3
690
君は古の言語M4を知っているか (LT)
makki_d
0
570
Featured
See All Featured
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
122
22k
Heart Work Chapter 1 - Part 1
lfama
PRO
7
36k
CoffeeScript is Beautiful & I Never Want to Write Plain JavaScript Again
sstephenson
162
16k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
13k
Building a Modern Day E-commerce SEO Strategy
aleyda
45
9.1k
brightonSEO & MeasureFest 2025 - Christian Goodrich - Winning strategies for Black Friday CRO & PPC
cargoodrich
3
720
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.5k
Thoughts on Productivity
jonyablonski
76
5.2k
The Art of Programming - Codeland 2020
erikaheidi
57
14k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
250
1.3M
Dealing with People You Can't Stand - Big Design 2015
cassininazir
367
27k
I Don’t Have Time: Getting Over the Fear to Launch Your Podcast
jcasabona
34
2.8k
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円) 既刊もよろしく