Types don't actually implement generic interfaces, they implement instantiations of generic interfaces. You can't use a generic type (including interfaces) without instantiation. From there, it is just like pre-generics Go, including the difference between methods with pointer receiver.
Therefore it is helpful to think what the methods that use type parameters would look like if you rewrote them with concrete types.
Let's consider a generic interface and some type:
type Getter[T any] interface {
Get() T
}
type MyStruct struct {
Val string
}
There's a few possible cases
Interface with concrete type argument
Getter[string]Get() string
// implements Getter[string]
func (m MyStruct) Get() string {
return m.Val
}
// ok
func foo() Getter[string] {
return MyStruct{}
}
Interface with type parameter as type argument
Getter[T]Get() T
Tstring
// Getter[T] literally needs implementors with `Get() T` method
func bar[T any]() Getter[T] {
return MyStruct{} // doesn't compile, even if T is string
}
MyStruct
type MyStruct[T any] struct {
Val T
}
func (m MyStruct[T]) Get() T {
return m.Val
}
func bar[T any]() Getter[T] {
return MyStruct[T]{} // ok
}
Concrete interface with generic implementor
MyStruct[T any]
type Getter interface {
Get() string
}
MyStructGetter
// Getter requires method `Get() string`
func baz() Getter {
return MyStruct[string]{} // instantiate with string, ok
// return MyStruct[int]{} // instantiate with something else, doesn't compile
}
Pointer receivers
This follows the same rules as above, but requires instantiating pointer types, as usual:
// pointer receiver, implements Getter[string]
func (m *MyStruct) Get() string {
return m.Val
}
func foo() Getter[string] {
return &MyStruct{} // ok
// return MyStruct{} // doesn't implement
}
MyStruct
// parametrized pointer receiver
func (m *MyStruct[T]) Get() T {
return m.Val
}
func foo() Getter[string] {
return &MyStruct[string]{} // ok
}
Dao[ReturnType]FindOne(id string) *ReturnType*MyDao
func NewMyDao() Dao[ReturnType] {
return &MyDao{}
}