func (c *Container) typesOf(instance interface{}, method string) (insType reflect.Type, funcType reflect.Type) {
	if method == "" {
		panic(fmt.Errorf("method must not be empty"))
	}
	insType = c.typeOf(instance)
	if insType.NumMethod() <= 0 {
		panic(fmt.Errorf("type %s has no method", insType.String()))
	}
	m, ok := insType.MethodByName(method)
	if !ok {
		panic(fmt.Errorf("no method named %s in type %s", method, insType.String()))
	}
	funcType = m.Type
	if insType.Kind() != reflect.Interface {
		ins := make([]reflect.Type, funcType.NumIn()-1)
		for i := 1; i < funcType.NumIn(); i++ {
			ins[i-1] = funcType.In(i)
		}
		outs := make([]reflect.Type, funcType.NumOut())
		for i := 0; i < funcType.NumOut(); i++ {
			outs[i] = funcType.Out(i)
		}
		funcType = reflect.FuncOf(ins, outs, funcType.IsVariadic())
	}
	return insType, funcType
}
typesOf returns instance type and func type.
package method
import (
	"fmt"
	"reflect"
	"sync"
)
var defaultContainer = NewContainer()
func Put(instance interface{}) {
	defaultContainer.Put(instance)
}
func PutInterface(iface interface{}, instance interface{}) {
	defaultContainer.PutInterface(iface, instance)
}
func Get(instance interface{}, method string) interface{} {
	return defaultContainer.Get(instance, method)
}
type Container struct {
	instances map[reflect.Type]interface{}
	lock      sync.RWMutex
}
func NewContainer() *Container {
	return &Container{
		instances: make(map[reflect.Type]interface{}),
	}
}
func (c *Container) Put(instance interface{}) {
	typ := reflect.TypeOf(instance)
	if typ.NumMethod() <= 0 {
		panic(fmt.Errorf("type %s has no method", typ.String()))
	}
	c.lock.Lock()
	defer c.lock.Unlock()
	c.instances[typ] = instance
}
func (c *Container) PutInterface(iface interface{}, instance interface{}) {
	typ := c.typeOf(iface)
	if typ.Kind() != reflect.Interface {
		panic(fmt.Errorf("type %s doesn't an interface", typ.String()))
	}
	if typ.NumMethod() <= 0 {
		panic(fmt.Errorf("type %s has no method", typ.String()))
	}
	c.lock.Lock()
	defer c.lock.Unlock()
	c.instances[typ] = instance
}
func (c *Container) funcOf(typ reflect.Type, method string) reflect.Value {
	c.lock.RLock()
	ins, ok := c.instances[typ]
	c.lock.RUnlock()
	if !ok {
		panic(fmt.Errorf("no instance for type %s", typ))
	}
	return reflect.ValueOf(ins).MethodByName(method)
}
func (c *Container) Get(instance interface{}, method string) interface{} {
	typ, funcTyp := c.typesOf(instance, method)
	var lock sync.Mutex
	var value *reflect.Value
	return reflect.MakeFunc(funcTyp, func(args []reflect.Value) (results []reflect.Value) {
		if value == nil {
			lock.Lock()
			if value == nil {
				v := c.funcOf(typ, method)
				value = &v
			}
			lock.Unlock()
		}
		return value.Call(args)
	}).Interface()
}