美文网首页
Invoke如何动态传参

Invoke如何动态传参

作者: 咕咕鷄 | 来源:发表于2017-01-20 09:42 被阅读0次

    原创文章转载请注明出处

    前文《go利用(*interface{})(nil)传递参数类型》介绍了Inject包是如何利用(*interface{})(nil)通过Map和MapTo将数据存储到values map[reflect.Type]reflect.Value这个map中。

    今天来聊聊Invoke方法

    // Invoke attempts to call the interface{} provided as a function,
    // providing dependencies for function arguments based on Type.
    // Returns a slice of reflect.Value representing the returned values of the function.
    // Returns an error if the injection fails.
    // It panics if f is not a function
    func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {
        t := reflect.TypeOf(f)
    
        var in = make([]reflect.Value, t.NumIn()) //Panic if t is not kind of Func
        for i := 0; i < t.NumIn(); i++ {
            argType := t.In(i)
            val := inj.Get(argType)
            if !val.IsValid() {
                return nil, fmt.Errorf("Value not found for type %v", argType)
            }
    
            in[i] = val
        }
    
        return reflect.ValueOf(f).Call(in), nil
    }
    

    其实没有太多有技术含量的东西,只要把反射吃透了,再弄清楚前文中MapMapTo存储的类型数据映射map,那么go的依赖注入就这么赤裸裸的展现在你眼前。

    将函数的值从空接口中反射出来,然后使用reflect.Call来传递参数并调用它。参数个数从t.NumIn()获取,循环遍历参数类型,再通过Get方法从values map[reflect.Type]reflect.Value获取对应类型的数据。

    func (i *injector) Get(t reflect.Type) reflect.Value {
        val := i.values[t]
    
        if val.IsValid() {
            return val
        }
    
        // no concrete types found, try to find implementors
        // if t is an interface
        if t.Kind() == reflect.Interface {
            for k, v := range i.values {
                if k.Implements(t) {
                    val = v
                    break
                }
            }
        }
    
        // Still no type found, try to look it up on the parent
        if !val.IsValid() && i.parent != nil {
            val = i.parent.Get(t)
        }
    
        return val
    
    }
    

    这里还有一篇文章《在 GOLANG 中用名字调用函数》,不是针对Martini的源码进行分析,但是读完以后你就会更明白为何Invoke方法要这么麻烦去用反射和依赖注入来书写。

    我是咕咕鸡,一个还在不停学习的全栈工程师。
    热爱生活,喜欢跑步,家庭是我不断向前进步的动力。

    相关文章

      网友评论

          本文标题:Invoke如何动态传参

          本文链接:https://www.haomeiwen.com/subject/zhtwbttx.html