That seems really difficult to retrofit, and to not really fit the language either.
I've been thinking something like sealed interfaces would fit better: Go already has fallible downcasts (and RTTI which takes the role of discriminant), and type switches can play the role of your `case` statement:
func do[T any](i option[T]) {
switch v := i.(type) {
case T:
fmt.Printf("Got a %v", v)
case nothing: // or `nil` could be a (pseudo)-type
fmt.Printf("was empty!")
// no default necessary because the check is complete
}
}
The only pieces missing are a way to "seal in" a set of types, and add completeness check to type switches for those.