zoukankan      html  css  js  c++  java
  • go inject 实践

    nject 是依赖注入的Go语言实现,它能在运行时注入参数,调用方法,是 Martini 框架(Go语言中著名的 Web 框架)的基础核心。

    demo1:

    package main
     
    import (
        "fmt"
     
        "github.com/codegangsta/inject"
    )
     
    type S1 interface{}
    type S2 interface{}
     
    func Format(name string, company S1, level S2, age int) {
        fmt.Printf("name = %s, company=%s, level=%s, age = %d!
    ", name, company, level, age)
    }
    func main() {
        //控制实例的创建
        inj := inject.New()
        //实参注入
        inj.Map("tom")
        inj.MapTo("tencent", (*S1)(nil))
        inj.MapTo("T4", (*S2)(nil))
        inj.Map(23)
        //函数反转调用
        inj.Invoke(Format)
    }

    可见 inject 提供了一种注入参数调用函数的通用功能,inject.New() 相当于创建了一个控制实例,由其来实现对函数的注入调用。inject 包不但提供了对函数的注入,还实现了对 struct 类型的注入,Apply 方法是用于对 struct 的字段进行注入,参数为指向底层类型为结构体的指针。可注入的前提是:字段必须是导出的(也即字段名以大写字母开头),并且此字段的 tag 设置为`inject`。示例代码如下所示

    package main
     
    import (
        "fmt"
        "github.com/codegangsta/inject"
    )
     
    type S1 interface{}
    type S2 interface{}
    type Staff struct {
        Name    string `inject`
        Company S1     `inject`
        Level   S2     `inject`
        Age     int    `inject`
    }
     
    func main() {
        //创建被注入实例
        s := Staff{}
        //控制实例的创建
        inj := inject.New()
        //初始化注入值
        inj.Map("tom")
        inj.MapTo("tencent", (*S1)(nil))
        inj.MapTo("T4", (*S2)(nil))
        inj.Map(23)
        //实现对 struct 注入
        inj.Apply(&s)
        //打印结果
        fmt.Printf("s = %v
    ", s)
    }

    另外 Injector 还规定了 SetParent 行为,它用于设置父 Injector,其实它相当于查找继承。也即通过 Get 方法在获取被注入参数时会一直追溯到 parent,这是个递归过程,直到查找到参数或为 nil 终止

    Map 和 MapTo 方法都用于注入参数,保存于 injector 的成员 values 中。这两个方法的功能完全相同,唯一的区别就是 Map 方法用参数值本身的类型当键,而 MapTo 方法有一个额外的参数可以指定特定的类型当键。但是 MapTo 方法的第二个参数 ifacePtr 必须是接口指针类型,因为最终 ifacePtr 会作为 InterfaceOf 方法的参数。
    为什么需要有 MapTo 方法?因为注入的参数是存储在一个以类型为键的 map 中,可想而知,当一个函数中有一个以上的参数的类型是一样时,后执行 Map 进行注入的参数将会覆盖前一个通过 Map 注入的参数。
    SetParent 方法用于给某个 Injector 指定父 Injector。Get 方法通过 reflect.Type 从 injector 的 values 成员中取出对应的值,它可能会检查是否设置了 parent,直到找到或返回无效的值,最后 Get 方法的返回值会经过 IsValid 方法的校验。

    demo3:

    package main
     
    import (
        "fmt"
     
        "github.com/codegangsta/inject"
    )
     
    type SpecialString interface{}
     
    func Say(name string, gender SpecialString, age int) {
        fmt.Printf("My name is %s, gender is %s, age is %d!
    ", name, gender, age)
    }
     
    /*
    func Say(name string, gender string, age int) {
        fmt.Printf("My name is %s, gender is %s, age is %d!
    ", name, gender, age)
    }
    */
    //没有定义 SpecialString 接口作为 gender 参数的类型,而把 name 和 gender 都定义为 string 类型,那么 gender 会覆盖 name 的值
    func main() {
        inj := inject.New()
        inj.Map("张三")
        inj.MapTo("", (*SpecialString)(nil))
        //inj.Map("男")
     
        inj2 := inject.New()
        inj2.Map(25)
        inj.SetParent(inj2)
        inj.Invoke(Say)
    }
  • 相关阅读:
    CVTE 一面
    【玩转Ubuntu】08. Linux报错:Syntax error: "(" unexpected解决办法
    Advanced Replication同步复制实验(基于Trigger&基于Materialized View)
    centos6.4-x86-64系统更新系统自带Apache Http Server
    针对某个表使用高级复制进行数据同步示例
    [置顶] What is the difference between Category and Class Extension?
    Boxes And Balls(三叉哈夫曼编码)
    xorequation(DFS完全枚举)
    Dreamoon and MRT(二元枚举)
    矩阵链乘(解析表达式)
  • 原文地址:https://www.cnblogs.com/majiang/p/14174050.html
Copyright © 2011-2022 走看看