reflect使用和源码阅读的心得笔记。golang
package main import ( "fmt" "reflect" ) type S struct { A float64 `usage:"a"` B float64 `usage:"b"` c float64 `usage:"c"` } func (s *S) Add() float64{ return s.A + s.B } func (s *S) Del()float64{ return s.A - s.B } func main() { s := S{1.43,2.15,3.24} t := reflect.TypeOf(s)//利用unsafe.Pointer的特性将S类型反射为emptyInterface类型,emptyInterface中的rtype定义与runtime里的_type对齐。 fmt.Println(t)//main.S fmt.Println(t.Field(1))//{B float64 usage:"b" 8 [1] false} 返回struct类型的第i个字段信息,从中能够获取到字段名,类型,tag,是否匿名等信息 fmt.Println(t.FieldByName("c"))//{c main float64 usage:"c" 16 [2] false} true fmt.Println(t.Field(1).Name)// B fmt.Println(t.Field(1).Type)// float64 fmt.Println(t.Field(1).Tag.Get("usage"))// b fmt.Println(t.Field(1).Anonymous)// false ps := reflect.TypeOf(&s) if ps.Kind() == reflect.Ptr{ e := ps.Elem()//用于取类型的element type,好比指针指向的类型,slice、Map、Array、channel里面成员的类型,非以上类型panic fmt.Println(e.Field(0))//{A float64 usage:"a" 0 [0] false} } //Slice的例子 list := make([]S,0) list = append(list, s) ps2 := reflect.TypeOf(list) if ps2.Kind() == reflect.Slice{ fmt.Println(ps2.Elem().Field(2))//{c main float64 usage:"c" 16 [2] false} } }
package main import ( "fmt" "reflect" ) type S struct { A float64 `usage:"a"` B float64 `usage:"b"` c float64 `usage:"c"` } func (s *S) Add() float64{ return s.A + s.B } func (s *S) Del()float64{ return s.A - s.B } func main() { s := S{1.43,2.15,3.24} v := reflect.ValueOf(s)//填充生成一个s具体类型对应的Value.此处实现也是使用unsafe.Pointer将S类型转换成emptyInterface类型的指针 fmt.Println(v)//{1.43 2.15 3.24} fmt.Println(v.Field(1))//2.15 只有值的信息 //fmt.Println(t.Method(0))//panic:由于方法的receiver类型是*S fmt.Println(v.Kind())//struct t := v.Type()//reflect.Value转换为reflect.Type fmt.Println(t.Field(2))//{c main float64 usage:"c" 16 [2] false} ps := &s pv := reflect.ValueOf(ps) fmt.Println(pv.Kind())//Ptr fmt.Println(pv.Elem())//{1.43 2.15 3.24} 返回指针ps指向或者interface ps包含的value,ps非这两种类型panic fmt.Println(pv.Elem().Field(1))//2.15 }
package main import ( "fmt" "reflect" ) type S struct { A float64 `usage:"a"` B float64 `usage:"b"` C float64 `usage:"c"` } func (s *S) Add() float64{ return s.A + s.B } func (s *S) Del()float64{ return s.A - s.B } func main() { a := S{1.43,2.15,3.24} b := S{1.11,2.22,3.33} va := reflect.ValueOf(a) vb := reflect.ValueOf(b) fmt.Println(va)// {1.43 2.15 3.24} fmt.Println(vb)// {1.11 2.22 3.33} //va.Field(0).SetFloat(1.11) //panic:using unaddressable value //va.Set(vb) //panic:using unaddressable value //上面两种方法不可设置va的值缘由以下: fmt.Println(va.CanSet())// false va不可设置,是否可设置是由Value的flag控制 //由于golang传参只有值传递因此va := reflect.ValueOf(a)实质上是取的a的副本的Value, //改变va是没法改变a的值的,正确作法以下 pva := reflect.ValueOf(&a) pva.Elem().Field(0).SetFloat(1.11) fmt.Println(pva.Elem())//{1.11 2.15 3.24} pva.Elem().Set(vb) fmt.Println(pva.Elem())//{1.11 2.22 3.33} }