string や int など、プリミティブな型は、それがゼロ値なのか、意図してその値になっているのかわからない時がある。
それを判別するために database/sql pkg などでは、NullString などの独自型を用意して、ゼロバリューなのかどうかを判定できるようにしている。
それをジェネリクスを使って、汎用的に書いてみたものが以下。
package main
import (
"fmt"
)
type NullValue[T any] struct {
value T
valid bool
}
func NewNullValue[T any](v T) NullValue[T] {
return NullValue[T]{
value: v,
valid: true,
}
}
func (nv NullValue[T]) Value() (T, bool) {
var noop T
if !nv.valid {
return noop, false
}
return nv.value, true
}
func main() {
print(NewNullValue("hogehoge")) // => hogehoge
print(NewNullValue("")) // =>
print(NullValue[string]{}) // => no value set
print(NewNullValue(100)) // => 100
print(NewNullValue(0)) // => 0
print(NullValue[int]{}) // => no value set
}
func print[T any](v NullValue[T]) {
if vv, ok := v.Value(); ok {
fmt.Println(vv)
} else {
fmt.Println("no value set")
}
}