Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Go1.20からサポートされるtree構造のerrの紹介と、treeを考慮した複数マッチができるライブラリを作った話/introduction of tree structure err added since go 1_20

convto
June 02, 2023

Go1.20からサポートされるtree構造のerrの紹介と、treeを考慮した複数マッチができるライブラリを作った話/introduction of tree structure err added since go 1_20

convto

June 02, 2023
Tweet

More Decks by convto

Other Decks in Technology

Transcript

  1. Go1.20から追加されたtree構造のerrの紹介と、
    treeを考慮した複数マッチができる
    ライブラリを作った話
    2023/06/02(金) Go Conference 2023 Online

    View Slide

  2. 自己紹介
    @convto
    株式会社LayerX所属
    レイヤ低めの技術などに興味がありま

    (ちなみにidの読みはこんぶとです)

    View Slide

  3. contents
    - tree構造のerrの紹介
    - proposalの議論などを
    おさらい
    - ありうるより高度なマッ
    チ要求
    - マッチ処理に関する実

    - 実験の考察
    - まとめ

    View Slide

  4. contents
    - tree構造のerrの紹介
    - proposalの議論などを
    おさらい
    - ありうるより高度なマッ
    チ要求
    - マッチ処理に関する実

    - 実験の考察
    - まとめ

    View Slide

  5. Go1.20で複数errをwrapできるようになった
    https://tip.golang.org/doc/go1.20#errors

    View Slide

  6. どういうことができるようになるか
    - こういうのができます
    - errをつくるときに複数errを合成できるように
    なり、マッチ処理でもそのような errが考慮さ
    れるようになる
    - あたらしいエラー構造とハンドリングが標準
    パッケージでサポートされる!

    View Slide

  7. いままでとなにがちがうか
    いままではこう
    - wrapされたerrの関係性は連結リスト的
    - 枝分かれなし
    errA errB errC errD

    View Slide

  8. いままではこう
    - wrapされたerrの関係性は連結リスト的
    - 枝分かれなし
    これからはこう
    - errorをたどると枝分かれしてる可能性があ

    - tree構造
    errA errB errC errD errA
    errB
    errC
    errD
    errC
    errD
    errD
    いままでとなにがちがうか

    View Slide

  9. contents
    - tree構造のerrの紹介
    - proposalの議論などを
    おさらい
    - ありうるより高度なマッ
    チ要求
    - マッチ処理に関する実

    - 実験の考察
    - まとめ

    View Slide

  10. proposal

    View Slide

  11. どういうproposal?
    - 複数errを一つのerrにしたい
    - `errors.Join()` や `fmt.Errorf()` で複数エラーの結合が可能に
    - 結合されたerrは `Unwrap() []error` を実装していて取り出し可能
    - 当初は `Split(error) []error` も提案されていた(後の議論でスコープ外に)

    View Slide

  12. Is/Asの探索はどのようなデザインか
    - treeを深さ優先探索する
    - マッチしたものがあればそこで探索を打ち切り結果を返す
    - tree上のすべての枝がIs/Asにマッチすることを保証しない
    - 当時存在したエコシステム上のmultierrライブラリの一般的な挙動などを参考にし
    て設定

    View Slide

  13. Is/Asの探索はどのようなデザインか
    errA
    errB
    errC
    errD
    errD
    errD
    errC

    View Slide

  14. Is/Asの探索はどのようなデザインか
    errA
    errB
    errC
    errD
    errC
    errD
    errD

    View Slide

  15. Is/Asの探索はどのようなデザインか
    errA
    errB
    errC
    errD
    errC
    errD
    errD

    View Slide

  16. Is/Asの探索はどのようなデザインか
    errA
    errB
    errC
    errD
    errC
    errD
    errD

    View Slide

  17. Is/Asの探索はどのようなデザインか
    errA
    errB
    errC
    errD
    errC
    errD
    errD

    View Slide

  18. 探索はどのようなデザインか
    - そんなに複雑でないし、あまり特別なこともし
    ていない
    - 枝分かれする探索部分のイメージをみると
    わかりやすいかも

    View Slide

  19. proposal中のデザインに関連する議論をピックアップ
    - SplitなりWalkなりの探索APIは検討しなくてよい?
    - IsとかAsの意味合いがすこし変わっちゃうけどよい?

    View Slide

  20. SplitなりWalkなりの探索APIは検討しなくてよい?

    View Slide

  21. もともとはproposalにsplitが含まれていたが...
    - 探索自体は需要あるかもだけど、デザインについて議論の余地があった
    - `Split()` or `Walk()` とか
    - まずはmultierrのコアとなる仕様だけstdに入れよう!
    - そうすればサードパーティで実験できるから、適切なデザインを探れる

    View Slide

  22. IsとかAsの意味合いがすこし変わっちゃうけどよい?

    View Slide

  23. どういうこと?
    - `Is()` はマッチした時点で探索をやめて true
    を返す
    - すべての分岐する枝で同一エラーかどうか
    を保証しない
    - ある枝はtrueでも別の枝でfalseなとき一部
    のエラーハンドリングで困るかも

    View Slide

  24. どういうこと?
    - `Is()` はマッチした時点で探索をやめて true
    を返す
    - すべての分岐する枝で同一エラーかどうか
    を保証しない
    - ある枝はtrueでも別の枝でfalseなとき一部
    のエラーハンドリングで困るかも
    err
    crit
    err
    ignorable
    err
    こういうtreeだったとき
    cliterrを見逃してしまうかも

    View Slide

  25. 最終的には提案された仕様のままとなった
    - 一瞬 `Contains()` と `Is()` を区別したほうが良いかもみたいなこと言ってる人はい

    - 既存multierr実装に合わせた形で仕様が提案されているので `Is()` が最初のマッ
    チで探索を打ち切る挙動は一般的に期待されるものと一致してるだろうという結論

    View Slide

  26. proposalふりかえりまとめ
    - tree構造を考慮したIs/Asが標準に追加
    - 探索APIなどは今のところ未提供で、要実験
    - マッチ処理も一部議論があったが提案通りの仕様で受け入れられた

    View Slide

  27. contents
    - tree構造のerrの紹介
    - proposalの議論などを
    おさらい
    - ありうるより高度なマッ
    チ要求
    - マッチ処理に関する実

    - 実験の考察
    - まとめ

    View Slide

  28. デザインのおさらい
    - treeを深さ優先探索する
    - マッチしたものがあればそこで探索を打ち切り結果を返す
    - tree上のすべての枝がIs/Asにマッチすることを保証しない

    View Slide

  29. 考えられる問題は?
    - As/Isで意味合いが変わるので一部コードに問題がでるかも(ほぼ影響なし)
    - 構造が複雑になったので、文脈によってより高度なマッチ処理がしたくなるかも

    View Slide

  30. 考えられる問題は?
    - As/Isで意味合いが変わるので一部コードに問題がでるかも(ほぼ影響なし)
    - 構造が複雑になったので、文脈によってより高度なマッチ処理がしたくなるかも

    View Slide

  31. 考えられる問題は?
    - As/Isで意味合いが変わるので一部コードに問題がでるかも(ほぼ影響なし)
    - 構造が複雑になったので、文脈によってより高度なマッチ処理がしたくなるかも
    -> いまのAPIでうまく探索できるのかが課題

    View Slide

  32. 例1: より正確なIs()

    View Slide

  33. errors.Is(errA, errD)
    errA
    errB
    errC
    errD
    errC
    errD
    errD

    View Slide

  34. errors.Is(errA, errD)
    errA
    errB
    errC
    errD
    errC
    errD
    errD
    これがhitした時点で探索やめちゃう

    View Slide

  35. errors.Is(errA, errD)
    errA
    errB
    errC
    errD
    errC
    errD
    errD
    これがhitした時点で探索やめちゃう
    このへんの枝がhitしてなくても
    true返す

    View Slide

  36. errors.Is(errA, errD)
    errA
    errB
    errD
    errD
    errD
    errE
    errE
    こういうときだけtrueかえしてほしい

    View Slide

  37. 例2: 全件抽出するAs()

    View Slide

  38. errors.As(errA, errD)
    errA
    errB
    errC
    errD
    errC
    errD
    errD
    これがhitした時点でerrDを返す

    View Slide

  39. errors.As(errA, errD)
    errA
    errB
    errC
    errD
    errC
    errD
    errD
    これがhitした時点でerrDを返す
    このへんも返してほしくない?

    View Slide

  40. errors.As(errA, errD)
    errA
    errB
    errC
    errD
    errC
    errD
    errD
    こういう結果を取り出したい

    View Slide

  41. 気になったので検証してみた
    - 例で上げた2つのマッチ処理を実装する
    - tree上のすべての枝に該当エラーが存在するか確認したい(例1)
    - tree上の該当エラーを枝などの関係性を問わずすべて抽出したい(例2)
    - いまの仕様で実装できるか試してみる

    View Slide

  42. contents
    - tree構造のerrの紹介
    - proposalの議論などを
    おさらい
    - ありうるより高度なマッ
    チ要求
    - マッチ処理に関する実

    - 実験の考察
    - まとめ

    View Slide

  43. 実験: より正確なIs()

    View Slide

  44. errors.Is(errA, errD)
    errA
    errB
    errD
    errD
    errD
    errE
    errE
    こういうときだけtrueかえしてほしい

    View Slide

  45. errors.Is(errA, errD)
    errA
    errB
    errC
    errD
    errD
    errE
    errE
    これはfalse

    View Slide

  46. そもそも標準のIsってどう探索してるんだっけ?
    - `Unwrap() error` と `Unwrap() []error` をア
    サーションして探索
    - 分岐してなければ剥がして終端でなければ
    loop
    - 分岐してれば各枝に再帰的に Is

    View Slide

  47. 枝が別れたら全部trueならtrueとすればよし
    - 分岐したときにマッチしない枝があれば false
    - ちなみに `Unwrap() []error` が len 0 となる
    ケースはいまの標準パッケージの実装では
    ないはず
    - いちおうproposalで空のケースが言及されて
    るのでみている

    View Slide

  48. 実験: 全件抽出するAs()

    View Slide

  49. errors.As(errA, errD)
    errA
    errB
    errC
    errD
    errC
    errD
    errD
    こういう結果を取り出したい

    View Slide

  50. どのようなものを作るか
    - Asのように具体的な型で取り出したい
    - `Scan[T any](err error, target T) (matched []T)` のようなデザインで考える
    - targetの具体的な型でmatchedを返せる
    - ただの抽出処理でありboolは返さないデザイン

    View Slide

  51. Scan実装
    - assignable or `As` 実装済みでマッチしたら
    結果に追加
    - 枝が分岐してなければ剥がして終端でなけ
    ればloop
    - 枝が分岐してれば再帰的に Scan

    View Slide

  52. contents
    - tree構造のerrの紹介
    - proposalの議論などを
    おさらい
    - ありうるより高度なマッ
    チ要求
    - マッチ処理に関する実

    - 実験の考察
    - まとめ

    View Slide

  53. ようはtreeへのマッチ処理で、さまざまな要求がありうる
    - tree上に該当エラーが1つ以上存在するか確認したい(go1.20のstd Isで提供され
    ているもの)
    - tree上に該当エラーが1つ以上存在するか確認して取り出したい(go1.20のstd As
    で提供されているもの)
    - tree上のすべての枝に該当エラーが存在するか確認したい(例1)
    - tree上の該当エラーを枝などの関係性を問わずすべて抽出したい(例2)

    View Slide

  54. ようはtreeへのマッチ処理で、さまざまな要求がありうる
    - tree上に該当エラーが1つ以上存在するか確認したい(go1.20のstd Isで提供され
    ているもの)
    - tree上に該当エラーが1つ以上存在するか確認して取り出したい(go1.20のstd As
    で提供されているもの)
    - tree上のすべての枝に該当エラーが存在するか確認したい(例1)
    - tree上の該当エラーを枝などの関係性を問わずすべて抽出したい(例2)
    - こういうのもあるかも
    - 例1と例2を組み合わせて「マッチ判定は tree上のすべての要素が対象、 hitしたものはすべて抽出」
    - etc..

    View Slide

  55. 実験前はこう思っていたけど...
    - 探索可能APIはほしいかも
    - joinしたerrをバラけさせるSplit()とか
    - errをバラして深さ優先探索して次の errを返すWalk()とか
    - 枝分かれする部分とそうじゃない部分を透過的に扱えると嬉しそう?

    View Slide

  56. 要求によっては連結リストと分岐部分を区別したいかも
    - 透過的な `Walk()` しちゃうと困るケースがあるかも
    - tree構造のerrは最近入ったばかりなので、エコシステム全体で実験を重ねていけ
    ばよりよい形が見えてくるのかも
    - そう考えるといまの `Upwrap() error` or `Unwrap() []error` で素朴に型判定する
    方針はよいバランス感覚かも?

    View Slide

  57. contents
    - tree構造のerrの紹介
    - proposalの議論などを
    おさらい
    - ありうるより高度なマッ
    チ要求
    - マッチ処理に関する実

    - 実験の考察
    - まとめ

    View Slide

  58. まとめ
    - 標準パッケージにtree構造のエラーへのサポートが入った
    - これによりエラーハンドリングにあたらしい複雑さが生まれた
    - 標準パッケージでは共通してみんなが使いそうなマッチ処理がサポートされている
    - 高度なマッチ処理がやりたかったら探索できるAPIがある
    - エコシステム全体で実験を重ねて知見をためればよりよい探索APIが見つかるかも
    - Goの簡素なエラー処理が個人的には好きなので、その性質を維持しつつよい方向
    に整理されていくとよいですね!

    View Slide

  59. ご清聴ありがとうございました

    View Slide