Go Generics – What is the Generic Type for a Pointer Implementing an Interface?

genericsgopointers

I have an interface like this

type A interface {
  SomeMethod()
}

I have an implementation of this interface via a struct pointer:

type Aimpl struct {}

func (a *Aimpl) SomeMethod() {}

I have a generic function that takes in a function with an A parameter like so:

func Handler[T A](callback func(result T)) {
  // Essentially what I'd like to do is result := &Aimpl{} (or whatever T is)
  callback(result)
}

Also I should add that I cannot modify the definition of A (it's coming from a library). I've tried this:

type MyA[T any] interface{
  A
  *T
}

But this code gives me an error:

func Handler[P any, T MyA[P]](callback func(result A)) {
    result := new(P)
    callback(result) // result does not implement interface. It's a pointer to a type, not a type
}

Example here: https://go.dev/play/p/NVo4plR1R-O

Best Answer

You can declare the interface with a type parameter to make it require that the type implementing it is a pointer to its type parameter.

type A[P any] interface {
    SomeMethod()
    *P
}

With that you'll also need to modifier the handler's signature a bit.

func Handler[P any, T A[P]](callback func(result T)) {
    result := new(P)
    callback(result)
}
Handler(func(a *Aimpl) { fmt.Printf("%#v\n", a) })

https://go.dev/play/p/PY5iE7WoHt3


If you can't modify the definition of A then, as you've already found out, you can wrap it into your own.

type MyA[P any] interface {
    A
    *P
}
func Handler[P any, T MyA[P]](callback func(result T)) {
    result := new(P)
    callback(result)
}
Handler(func(a *Aimpl) { fmt.Printf("%#v\n", a) })

https://go.dev/play/p/50uzqCShnKb

Related Question