2025/03/16 03:32 Decoding JSON sum types in Go without panicking

やあ、ロボ子。今日はGo言語でのJSONのsum typesの扱い方について話すのじゃ。

sum types、ですか。複数の異なる型のうちの1つを取りうるデータ構造のことですね。Goにはネイティブサポートがないんですよね。

そうなんじゃ。だからエミュレートする必要があるんじゃが、安易に実装するとnil pointer panicが発生する可能性があるのが問題なんじゃ。

JSONのデコード時に、すべてのフィールドを持つ構造体を使うと、未使用のフィールドがnilになってしまうからですね。

その通り!そこで、OpenAPI GeneratorやProtocol Buffers (Protobuf) のコード生成を利用すると、より型安全な実装が可能になるんじゃ。

OpenAPI Generatorは、discriminatorに基づいて適切な型をUnmarshalするコードを生成してくれるんですね。

そうじゃ。他にも、Sealed Interfaceを使って、sum typeのバリアントを同じパッケージ内で定義する方法もあるぞ。これにより、インターフェースを満たす型セットがコンパイル時に閉じられることが保証されるんじゃ。

なるほど。それと、go-check-sumtypeというlinterを使うと、switch文でバリアントの処理漏れをコンパイル時に検出できるんですね。

そうじゃ!ActionのTypeをEnumで定義して、不正なActionTypeを検知できるようにするのも有効じゃな。

UnmarshalJSON/MarshalJSONを実装して、JSONのデコード/エンコード処理を自分で書くこともできますね。

JSONの表現方法も色々あるんじゃ。internally tagged、adjacently tagged、externally taggedと、状況に応じて使い分けるのが良いぞ。

V言語のように、enumsとsum typesをネイティブサポートする言語もあるんですね。Goに似た構文を持ちながら、match式によるexhaustive checkingができるのは魅力的です。

色々な言語での実装例を知っておくと、Goで実装する際の参考になるじゃろう。例えば、RustやTypeScriptでもsum typesは強力な機能として提供されているぞ。

勉強になります!Goでsum typesを扱うのは少し大変ですが、色々な方法があることがわかりました。

そうじゃな。しかし、これらの方法を駆使しても、最終的にpanicを完全に回避できるとは限らないのが、また面白いところなんじゃ。

ええっ、そうなんですか?

まあ、人生もsum typeみたいなものじゃからな!

どういうことですか?

どの型になるか、最後までわからない!
⚠️この記事は生成AIによるコンテンツを含み、ハルシネーションの可能性があります。