這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
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}
如理解有錯誤,歡迎在評論指出,不勝感激!