Go

Explain the "pointer method" constraint pattern (PT interface{ *T; M() }). Why is it needed?

Question 127HardGo 1.22 to 1.25

Problem: you want to create values of type T inside a generic function and call a method that has a pointer receiver, such as UnmarshalText or Set. T itself does not have that method in its method set, and *T does, but there is no way to say "*T has method M" directly. The fix is a second type parameter that is constrained to be *T and to have the method.

type Setter[T any] interface {
    *T                   // PT must be exactly *T
    Set(string) error    // ...and have Set
}

func ParseAll[T any, PT Setter[T]](in []string) ([]T, error) {
    out := make([]T, len(in))
    for i, s := range in {
        p := PT(&out[i]) // convert *T to PT
        if err := p.Set(s); err != nil {
            return nil, err
        }
    }
    return out, nil
}

type Level int

func (l *Level) Set(s string) error {
    n, err := strconv.Atoi(s)
    *l = Level(n)
    return err
}

// PT inferred as *Level via constraint type inference
levels, err := ParseAll[Level]([]string{"1", "2", "3"})

If you wrote func ParseAll[T Setter](...) instead, callers would pass *Level. var zero T would then be a nil pointer, and calling Set would panic. Interviewers are checking that you know the relationship between method sets and pointers, and the nil-pointer trap.

More on Generics

All 36 Generics questions