這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
隨學隨記,留備查
1、初學web設計,暫不想使用第三方庫;於是乎HandleFunc()寫的滿屏都是……就想著類比MVC思想,根據URL的路徑自動調用指定的控制器方法,豈不是很好;
2、嘗試使用Go的反射功能,初步實現了原理演算法;
3、需要引入“reflect”包,使用reflect.ValueOf()方法,這裡必須傳入參數地址,否則其返回的reflect.Value類型只能查詢到靜態聲明的方法,不能得到動態綁定的方法;
4、即使傳入參數地址,其返回的reflect.Value類型,也得不到方法名;Go的意思應該是值和類型分開處理,在類型裡面才有名稱等資訊;
4、需要再次調用傳回值的Type()方法,這樣就可以查詢方法名稱;
5、然後將方法名稱和方法指標存入Map中,後續通過Map[name]的方式根據方法名字串調用對應的方法;
package mainimport ("fmt""reflect")//定義控制器函數Map類型,便於後續快捷使用type ControllerMapsType map[string]reflect.Value//聲明控制器函數Map類型變數var ControllerMaps ControllerMapsType//定義路由器結構類型type Routers struct {}//為路由器結構附加功能控制器函數,值傳遞func (this *Routers) Login(msg string) {fmt.Println("Login:", msg)}//為路由器結構附加功能控制器函數,引用傳遞func (this *Routers) ChangeName(msg *string) {fmt.Println("ChangeName:", *msg)*msg = *msg + " Changed"}func main() {var ruTest RouterscrMap := make(ControllerMapsType, 0)//建立反射變數,注意這裡需要傳入ruTest變數的地址;//不傳入地址就只能反射Routers靜態定義的方法vf := reflect.ValueOf(&ruTest)vft := vf.Type()//讀取方法數量mNum := vf.NumMethod()fmt.Println("NumMethod:", mNum)//遍曆路由器的方法,並將其存入控制器映射變數中for i := 0; i < mNum; i++ {mName := vft.Method(i).Namefmt.Println("index:", i, " MethodName:", mName)crMap[mName] = vf.Method(i) //<<<}//示範testStr := "Hello Go"//建立帶調用方法時需要傳入的參數列表parms := []reflect.Value{reflect.ValueOf(testStr)}//使用方法名字串調用指定方法crMap["Login"].Call(parms)//建立帶調用方法時需要傳入的參數列表parms = []reflect.Value{reflect.ValueOf(&testStr)}//使用方法名字串調用指定方法crMap["ChangeName"].Call(parms)//可見,testStr的值已經被修改了fmt.Println("testStr:", testStr)}