Some notes about Golang Generics and Abstraction based on my working experience.
WARNING
Under construction.
Use ‘generic interface’ when you need to self-reference the interface in the methods of your interface
TIP
Important references:
For Example:
Before we have generics:
type MyInterface interface {
  DoSomething(MyInterface)
}
 
type MyConcreteType struct{}
 
func (m MyConcreteType) DoSomething(m2 MyInterface) {} // Here we have to use 'MyInterface' instead of 'MyConcreteType' !Note that m2 MyInterface argument. We can’t use ‘concrete’ type here.
The consequence is that we will have to do a dynamic type assertion to get the concrete type
for every implementation.
With generics:
type MyInterface[T any] interface {
  DoSomething(T)
}
 
type MyConcreteType struct{}
func (m MyConcreteType) DoSomething(m2 MyConcreteType) {} // Here we can use 'MyConcreteType' directly !NOTE
注意这个东西,it is used as the type constraint in the type parameter in the code of the generic interface user.
但是你肯定有疑问:DoSomething 如果不是 receiver 和 argument 不是同一个 type,不是还是有这个问题吗? 确实如此:
type GenericInterface[T any] interface {
	DoSomething(T)
}
type ConcreteType struct{}
func (m ConcreteType) DoSomething(m2 ConcreteType) {}
 
type AnotherType struct{}
func (a AnotherType) DoSomething(m2 ConcreteType) {}
 
var (
	_ GenericInterface[ConcreteType] = ConcreteType{}
  // The exact example of receiver type != argument type.
	_ GenericInterface[ConcreteType] = AnotherType{}
)但是可惜,这方面只能是这样了。实际上只能在 user end 来让 compiler 知道 “对于这个 interface,receiver type 和 argument type 应该一样“
func FuncUserOfGenericInterface[T MyInterface[T]](arg T) {
  arg.DoSomething(arg) // This is OK.
}
 
type TypeUserOfGenericInterface[T MyInterface[T]] struct {
  value T
}
 
func (t TypeUserOfGenericInterface[T]) method() {
  t.value.DoSomething(t.value) // This is OK.
}In the example above:
- The T MyInterface[T]enforced the reciver type and the argument type must be the same.
Functor and single-method interface conversion
这两个虽然有很多相似的地方,而且如果 functor 可以直接当作 implementation for single-method interace,可能很多代码可以简化。
但是从 type system 的角度看,就是不一样的东西。两者之间也没有办法互相 cast。
Here is the not-planned proposal for Golang 2: https://github.com/golang/go/issues/21670
但是现实中我们可以看到很多地方用了 http.HandlerFunc 这个 functor type 来当作 http.Handler 的 implementation. 为什么呢?
Because: code
// Yes, this is a functor type.
type HandlerFunc func(ResponseWriter, *Request)
 
// But it also has a specific method to implement the handler interface 
func (f HandlerFunc) ServeHTTP(w ResponseWriter, r *Request) {
	f(w, r)
}So, if you do want to let a ‘functor’ type to implement a single-method interface, you still need to explicitly implement the method for the interface:
type yourFunctorType func(xxx) yyy
 
// This is needed to implement interface `YourInterface` which has a method: `YourInterfaceMethod(xxx) yyy`
func (f yourFunctorType) YourInterfaceMethod(xxx) yyy {
}