/*
参数c是个指针,可能指向各种类型的结构体,所以此时无法使用c
所以总体思路就是:新申请一块内存,类型和c一模一样,并且把所需的value都拷贝过来
用反射获取一个未知变量的类型和值 -> 据此New一个新的变量 -> 还原成原始变量(此时是空值)-> 逐个字段把所需值拷贝到新的内存
涉及到的知识点:根据反射获取未知变量的属性,把反射对象还原成原始数据,修改反射类型字段值
参考:https://ehlxr.me/2018/01/26/golang-reflect/
*/
func (p *ControllerRegister) addWithMethodParams(pattern string, c ControllerInterface, methodParams []*param.MethodParam, mappingMethods ...string) {
//因为c是指针,所以要用Indirect方法获取指针指向的变量类型
reflectVal := reflect.ValueOf(c)
t := reflect.Indirect(reflectVal).Type()
route.initialize = func() ControllerInterface {
//New()返回的是指针,再把它还原成c,此时已新申请一块内存,类型和c一模一样
vc := reflect.New(t)
execController, ok := vc.Interface().(ControllerInterface)
elemVal := reflect.ValueOf(c).Elem()
elemType := reflect.TypeOf(c).Elem()
execElem := reflect.ValueOf(execController).Elem()
//判断c指向的变量有几个字段,再逐个把所需的拷贝到新的内存里
numOfFields := elemVal.NumField()
for i := 0; i < numOfFields; i++ {
fieldType := elemType.Field(i)
elemField := execElem.FieldByName(fieldType.Name)
if elemField.CanSet() {
fieldVal := elemVal.Field(i)
elemField.Set(fieldVal)
}
}
//execController就是我们所需的变量
return execController
}
...
}