Go 1.22 のリリースが近づいていますが、その中でdatabase/sqlにNull[T]
を追加したので紹介しておきます。
database/sql
パッケージにはNullByte
,NullBool
,NullFloat64
,NullInt64
などのNullableなカラムを扱うための型が用意されているのですが、NullUInt64
はありませんでした。
UInt型が標準的ではなく、driver.Value
にもuint64が含まれていないからです。
一方でMySQLはunsigned tinyint~bigint型があるのでgo-mysql-driverもuint64には対応しています。32bitまではint64で、64bitではuint64で扱うようになっています。
だからと言ってドライバー独自に NullUInt64
を提供すると、他のパッケージも同じ型を提供した時に混乱の元です。
ということで、ジェネリクスを使って sql.Null[T]
を追加してもらうことにしました。
一番難しかったのはメンバーのネーミングです。例えば NullInt64 の定義は次のようになっています。
type NullInt64 struct { Int64 int64 Valid bool // Valid is true if Int64 is not NULL }
値が入っているメンバーの名前が、型の名前の先頭が大文字になったものになっているんですね。NullTime
型の場合はTime time.Time
です。しかしこれに一貫性を持たせようとすると T T
になるのでちょっと混乱します。
一番に思いつく名前はValueなのですが、これらの型はValuerインターフェイスを実装していて Value()
メソッドを追加する必要があるので、Valueも使えません。
Valにすると、Val, Valid, Value() が並ぶことになってしまい、これもあまり良くありません。
最終的に名前は V T
になりました。型名と値の名前が同じ1文字どうしなので Int64 int64
と同じくらいのペア感があり、 Val に比べると Valid, Value() との距離も少し離れたので、一番マシな選択肢だったと思います。
なお、データベースとのやりとりを目的として、Scanner/Valuerインターフェイスを実装するように設計した型なので、一般的な Optional 型の代わりに使おうとは思わないでくださいね。