golang martini 源碼閱讀筆記之inject

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

martini是go語言寫的一個超級輕量的web開源架構,具體源碼可在github搜尋找到。13年那會開始接觸go語言時有稍微看過這個架構,由於之後沒有繼續使用go就慢慢忽略了,最近由於手頭項目可能會用到,因此又想起這個架構。

github上顯示該項目更新不斷,說明真是個好架構,簡潔高效的東西從來都不缺少擁護者。周末閱讀martini源碼時做了注釋寫下一些理解,主要是inject.go以及martini.go兩個檔案,後續估計還會再閱讀路由功能的主要檔案。

註:以下的'泛型'均表示interface{}類型

inject.go

package injectimport (    "fmt"    "reflect")// 實現回呼函數參數值的注入,通觀martini架構,Injector就是用於儲存中介軟體函數以及使用者自訂函數回調時的參數type Injector interface {    Applicator // 結構體各個欄位賦值    Invoker     // 通過反射實現函數調用的介面    TypeMapper  // 類型映射介面,TypeMapper 的功能與系統設計初衷有關係吧,mapper根據類型為索引值key,同一類型只有一個value與之對應    SetParent(Injector)}// 為結構體類型的各個欄位進行動態賦值type Applicator interface {    // 為結構體定義中,帶有'inject'標籤的欄位進行賦值    Apply(interface{}) error}// 通過反射的方式實現函數調用type Invoker interface {    // 參數類型為函數類型,使用反射擷取函數參數類型,根據各個參數類型擷取對應的值,並調用該函數    Invoke(interface{}) ([]reflect.Value, error)}// 參數值與類型的映射介面type TypeMapper interface {    // 具體類型的映射,根據值的具體類型直接建立映射    Map(interface{}) TypeMapper     // ’泛型‘與具體類型之間的映射,第二個參數必須是泛型的指標類型    // 因為這裡只需要獲得泛型的類型,只有泛型的指標代價最小了,因為只需要用到它的type部分    // 這裡需要理解interface{}的具體實現    MapTo(interface{}, interface{}) TypeMapper     Set(reflect.Type, reflect.Value) TypeMapper    Get(reflect.Type) reflect.Value // 根據類型尋找值}//這裡類似於將所有的golang類型分為兩種大的類型:泛型 interface{}與具體類型concrete typetype injector struct {    values map[reflect.Type]reflect.Value // 儲存上述過程中結構體欄位的值,以及函數調用參數的值    parent Injector // }// 查詢 value 的介面類型, 適用於interface{}類型的映射, 如果value不是指標類型將會返回異常// 這個介面只是用在泛型映射,因此只需要從value(interface{})中擷取type部分func InterfaceOf(value interface{}) reflect.Type {    t := reflect.TypeOf(value) // 擷取type的值    for t.Kind() == reflect.Ptr { // 如果是指標,繼續查指標的指向        t = t.Elem() // 指標指向的元素     }    if t.Kind() != reflect.Interface { // 最後肯定是指向interface 了,如果不是,說明傳入的參數有問題        panic("Called inject.InterfaceOf with a value that is not a pointer to an interface. (*MyInterface)(nil)")    }    return t}// New returns a new Injector.//建立一個注入工具,提供資料存放區與查詢,其他功能主要還是依賴於反射庫的實現func New() Injector {    return &injector{        values: make(map[reflect.Type]reflect.Value),    }}// 參數類型為函數func,使用反射介面完成函數的調用func (inj *injector) Invoke(f interface{}) ([]reflect.Value, error) {    t := reflect.TypeOf(f) //擷取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    }    // 反射類型的函數調用,取出f中的資料部分,即執行個體值函數    return reflect.ValueOf(f).Call(in), nil // 函數調用}// 為結構體賦值的具體實現func (inj *injector) Apply(val interface{}) error {    v := reflect.ValueOf(val)    for v.Kind() == reflect.Ptr {        v = v.Elem()    }    if v.Kind() != reflect.Struct {        return nil // Should not panic here ?    }    t := v.Type() // 擷取結構體的類型    for i := 0; i < v.NumField(); i++ { // 擷取欄位的數量        f := v.Field(i)        structField := t.Field(i)        // 帶有'inject'標籤的才可能被賦值        if f.CanSet() && (structField.Tag == "inject" || structField.Tag.Get("inject") != "") {            ft := f.Type()            v := inj.Get(ft)            if !v.IsValid() {                return fmt.Errorf("Value not found for type %v", ft)            }            f.Set(v)        }    }    return nil}// 具體型別參數,類型與值的映射func (i *injector) Map(val interface{}) TypeMapper {    //類型與值的映射    i.values[reflect.TypeOf(val)] = reflect.ValueOf(val)    return i}// 泛型型別的映射func (i *injector) MapTo(val interface{}, ifacePtr interface{}) TypeMapper {    //需要先擷取泛型指標指向的具體泛型型別    i.values[InterfaceOf(ifacePtr)] = reflect.ValueOf(val)    return i}func (i *injector) Set(typ reflect.Type, val reflect.Value) TypeMapper {    i.values[typ] = val    return i}//  根據類型尋找值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 { // t 為 interface 類型        for k, v := range i.values {  // 迭代查詢            if k.Implements(t) {    // 對於每一個類型,看是否實現了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}func (i *injector) SetParent(parent Injector) {    i.parent = parent}

 

如理解有錯誤,歡迎在評論指出,不勝感激!

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.