网站建设工作分解结构词典,网页升级访问中新每天正常更新中,服务器建设网站软件,湖南长工工程建设有限公司官方网站文章目录 获取类型和值获取属性的类型和值通过反射修改值获取方法的名称和类型调用方法反射的缺点 获取类型和值
之前讲过接口nil不一定等于空接口#xff0c;因为一个 interface 底层 由 type value 构成#xff0c;只有 type 和 value 都匹配#xff0c;才能 reflect.Vl… 文章目录 获取类型和值获取属性的类型和值通过反射修改值获取方法的名称和类型调用方法反射的缺点 获取类型和值
之前讲过接口nil不一定等于空接口因为一个 interface 底层 由 type value 构成只有 type 和 value 都匹配才能 reflect.VlaueOf 就是用来获取具体的 reflect.Valuereflect.TypeOf 用来获取具体的 reflect.Type
func main() {var (a *Ab interface{})fmt.Println(a)if b nil {fmt.Println(b is nil)}fmt.Println(reflect.TypeOf(b), reflect.ValueOf(b))fmt.Println(reflect.TypeOf(a), reflect.ValueOf(a))b aif b nil {fmt.Println(b is nil)} else {fmt.Printf(current b is %v \n, b)fmt.Println(b not eq nil)}fmt.Println(reflect.TypeOf(b), reflect.ValueOf(b))
}上面的代码说明了刚开始的空接口 nil后来的接口为啥不等于 nil因为 type变了虽然value 还是 nil
获取属性的类型和值
通过 reflect.Value 或者 reflect.Type 的 NumField 获取属性数量通过 reflect.Type 的 Field 方法 获取属性相关信息通过 reflect.Value 的 Field 方法 获取值相关信息
package mainimport (fmtreflect
)type A struct {Name stringAge int
}func main() {var a AgetType : reflect.TypeOf(a)getValue : reflect.ValueOf(a)fmt.Println(field num, getType.NumField())for i : 0; i getType.NumField(); i {field : getType.Field(i)value : getValue.Field(i)fmt.Println(field name is, field.Name, field value is, value.Interface())}
} 通过反射修改值
通过获取value的反射对象即可reflect.ValueOf 传入的必须是指针类型只有原始反射对象可以进行修改可以通过 reflect.Value 的 Elem 方法取得通过 reflect.Value 的 Canset 方法来判断是否可以设置通过 Set... 系列方法来设置具体类型的值
package mainimport (fmtreflect
)type A struct {Name stringAge int
}func main() {a : A{Name: old name,}valueOfA : reflect.ValueOf(a).Elem()nameField : valueOfA.Field(0)if nameField.CanSet() {nameField.SetString(new name)} else {fmt.Println(dont set)}fmt.Println(new value, a.Name)
}
因为调用 set... 设置值需要知道类型可以通过 reflect.Type 的 kind 方法获取原始类型 再通过 switch 去匹配类型来调用具体的 set... 方法
package mainimport (fmtreflect
)type A struct {Name stringAge int
}func main() {a : A{Name: old name,}fmt.Println(old value, a.Name)valueOfA : reflect.ValueOf(a).Elem()getType : reflect.TypeOf(a)field : getType.Field(0)nameField : valueOfA.Field(0)if nameField.CanSet() {switch field.Type.Kind() {case reflect.String:fmt.Println(string)nameField.SetString(new value)}} else {fmt.Println(dont set)}fmt.Println(new value, a.Name)
}获取方法的名称和类型
先通过 reflect.Type 的 NumMethod 方法获取方法数量在通过 reflect.Type 的 Method 方法获取到具体的方法信息 reflect.Method
package mainimport (fmtreflect
)type A struct {Name stringAge int
}func (receiver *A) SetName(name string) {receiver.Name name
}func (receiver *A) SetAge(age int) {receiver.Age age
}func main() {var a A//有方法是依赖指针的所以需要传指针getType : reflect.TypeOf(a)num : getType.NumMethod()for i : 0; i num; i {method : getType.Method(i)fmt.Println(method name:, method.Name, method type:, method.Type)}
} 调用方法
通过 reflect.Method 的 Call 方法即可调用反射对象的方法 Call 中 接收的参数为 reflect.Value 的切片如果反射对象的方法不需要参数传一个 reflect.Value 的空切片即可如果反射对象需参数那么需要由反射对像参数的 reflect.Value 组成切片传入 Call 完成调用
package mainimport (fmtreflect
)type A struct {Name stringAge int
}type Body struct {Like stringDesc string
}func (a A) Pr() {fmt.Println(A pr)
}func (a A) Talk(b Body) {fmt.Printf(Like:%s,Desc:%s, b.Like, b.Desc)
}func main() {var a AgetType : reflect.ValueOf(a)pr : getType.Method(0)//不需要参数pr.Call([]reflect.Value{})b : Body{Like: im like,Desc: im desc,}talk : getType.Method(1)//Talk 需要传入 Body struct, 所以反射调用需要传入 由 Body的 reflect.Value 组成切片参数talk.Call([]reflect.Value{reflect.ValueOf(b),})
} 反射的缺点
反射慢 不管什么编程语言反射都慢反射实现里有对 reflect.kind 大量的枚举 类型转换 等操作reflect.Value 不能复用每次都是返回一个新的值其中 typ 还是指针类型涉及对指针的频繁分配GC