OK thank you everyone for your answers. I noticed that I can write a type constraint which is a union of string | *regexp.Regexp. It's very useful for a function that receives a regexp, or a string that will be compiled to a regexp. In my implementation, I convert the parameter ton any, then I do a type switch.
In another function I want to receive a parameter with a type constraint which is a union of Equal(T) bool | Compare(T) int because I want to either use Equal() or Compare() to check the type equality, depending on which method is available. Unfortunately this is not allowed. I can use the type any, but it is less safe. As mentioned in this conversation, I decided to implement 2 functions instead (1 for each method) Le samedi 14 mars 2026 à 07:14:39 UTC+1, Kurtis Rader a écrit : > You wrote: > > > This is of course somewhat error prone, you might easily forget a branch > or otherwise screw up the logic of your function. > > That is precisely my point. If you have to include explicit run-time type > checks in your function to support the type polymorphism then you cannot > assume the compiler will not allow an unexpected type to leak into your > function. Especially since the type signature might be modified without the > implementation being updated to correctly handle the new type signature. > > On Fri, Mar 13, 2026 at 11:06 PM Axel Wagner <[email protected]> > wrote: > >> >> On Sat, 14 Mar 2026 at 06:49, Kurtis Rader <[email protected]> wrote: >> >>> I guess I'm showing my age. But if you have to write an explicit run >>> time type switch/assertion then you should assume the compile time type >>> constraint might allow an unexpected type to "leak" into your function. >>> >> >> I don't understand this assertion. It seems plain untrue to me. If we >> allowed you to write `fmt.Stringer | ~string` (and put a SAT solver into >> the compiler to do the appropriate checks) but otherwise not changed the >> language at all, then this would be accepted by the compiler: >> >> func Stringify[T interface{ ~string | fmt.Stringer}](v T) string { >> // still have to write the type switch >> switch v := any(v).(type) { >> case fmt.Stringer: >> return v.String() >> default: >> return reflect.ValueOf(v).String() >> } >> } >> >> This is of course somewhat error prone, you might easily forget a branch >> or otherwise screw up the logic of your function. But it would mean this is >> rejected by the compiler: >> >> func main() { >> println(Stringify[int](42)) >> } >> >> If, instead, you use `T any`, this program would be allowed and panic at >> runtime. >> >> >>> If the O.P.'s example was supported by the compilation toolchain that >>> might be impossible, in theory, but I would assume it's still possible if I >>> have to write code to disambiguate which type I received. >>> >>> -- >>> Kurtis Rader >>> Caretaker of the exceptional canines Junior and Hank >>> >> > > -- > Kurtis Rader > Caretaker of the exceptional canines Junior and Hank > -- You received this message because you are subscribed to the Google Groups "golang-nuts" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To view this discussion visit https://groups.google.com/d/msgid/golang-nuts/12e6fa3a-8599-4ff3-8547-84297e53201an%40googlegroups.com.
