在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
本文内容是本人对Go语言的反射原理与使用的备忘录,记录了关键的相关知识点,以供翻查。 文中如有错误的地方请大家指出,以免误导!转摘本文也请注明出处:Go语言备忘录(2):反射的原理与使用详解,多谢! 参考书籍《The Go Programming Language》、《Go In Action》、《Go语言学习笔记》等 目录:
1.预备知识:
3.reflect包的两个主要类型Value、Type:这两种类型都提供了大量的方法让我们可以检查和操作这两种类型
v := reflect.ValueOf(&x) m := v.MethodByName("Show") in := []reflect.Value{ reflect.ValueOf(23), reflect.ValueOf(323), } out := m.Call(in) //对于变参可用CallSlice方法
对于一个settable的Value反射对象,如 d := reflect.ValueOf(&x).Elem():
通过一个settable的Value反射对象来访问、修改其对应的变量的方式:
var x float64 = 3.4 p := reflect.ValueOf(&x) // 注意这里:把x地址传进去了! fmt.Println(p.Type()) //*float64 fmt.Println(p.CanSet()) //false 这里的p只是指针,仍然是non-settable的 v := p.Elem() //此时的v保存了x fmt.Println( v.CanSet()) //true v.SetFloat(7.1) fmt.Println(v.Interface()) //7.1 fmt.Println(x) //7.1 虽然反射可以越过Go语言的导出规则的限制读取结构体中未导出的成员,但不能修改这些未导出的成员。因为一个struct中只有被导出的字段才是settable的。 type T struct { A int B string } t := T{23, "skidoo"} s := reflect.ValueOf(&t).Elem() typeOfT := s.Type()//把s.Type()返回的Type对象复制给typeofT,typeofT也是一个反射。 for i := 0; i < s.NumField(); i++ { f := s.Field(i)//迭代s的各个域,注意每个域仍然是反射。 fmt.Printf("%d: %s %s = %v\n", i, typeOfT.Field(i).Name, f.Type(), f.Interface())//提取了每个域的名字 } //0: A int = 23 //1: B string = skidoo s.Field(0).SetInt(77) //s.Field(0).Set(reflect.ValueOf(77)) s.Field(1).SetString("Sunset Strip") fmt.Println("t is now", t) //t is now {77 Sunset Strip}
package main import ( "reflect" "strings" "fmt" ) //通用算法函数体模板 func add(args []reflect.Value) (results []reflect.Value) { if len(args) == 0 { return nil } var r reflect.Value switch args[0].Kind() { case reflect.Int: n:=0 for _,a:=range args{ n+=int(a.Int()) } r = reflect.ValueOf(n) case reflect.String: ss := make([]string,0,len(args)) for _,s:=range args{ ss = append(ss,s.String()) } r=reflect.ValueOf(strings.Join(ss,"")) } results = append(results,r) return } func makeAdd(T interface{}) { fn:=reflect.ValueOf(T).Elem() v:=reflect.MakeFunc(fn.Type(),add) //把原始函数变量的类型和通用算法函数存到同一个Value中 fn.Set(v) //把原始函数指针变量指向v,这样它就获得了函数体 } func main() { //定义函数变量,未定义函数体 var intAdd func(x,y int) int var strAdd func(a,b string) string makeAdd(&intAdd) makeAdd(&strAdd) fmt.Println(intAdd(12,23)) //35 fmt.Println(strAdd("hello, ","world!")) //hello, world! } 最后,反射对性能有一定的影响,如对性能要求较高,须谨慎使用反射!
|
请发表评论