反射 reflection golang

2020-09-06  本文已影响0人  与子笑
type User struct {    
    Name string    
    Age  int    
    Id   int
    }
func (u User) GetName(name string) { //将匿名方法绑定到结构体中    
    fmt.Println("我的名字叫", u.Name, "传进来的是", name)
    }
func main() {    
    a := User{"xiaoming", 5, 6}    
    a.GetName("测试1")    
    Setname(&a)    
    a.GetName("测试2")    
    fmt.Println(a.Name)    
    info(a)    
    ra := reflect.ValueOf(a)    
    rm := ra.MethodByName("GetName")    
    args := []reflect.Value{reflect.ValueOf("测试三")} //通过反射调用该对象方法    
    //这里再次回到切片与数组。到底什么是切片,什么是数组    
    //再次总结一下,刚看了点资料,以下是链接    
    <https://www.zhihu.com/question/66673454>    
    //以下是总结    
    //1.数组要指明长度Array := [ArrayLength] ElementType,arr :=[4]int,数组拷贝为值拷贝    
    //2.切片不需要指明长度SliceT := []ElementType,但是他有容量机制,拷贝为指针拷贝    
    arr := [4]int{0, 1, 3, 4}    
    arrs := arr[1:2]    
    ccc := reflect.TypeOf(arrs).Kind() //通过反射判断是一个数组还是切片    
    fmt.Println(ccc)    
    rm.Call(args)}func info(o interface{}) { //获取这个实例化了的结构体的所有信息    
        ot := reflect.TypeOf(o)  //通过反射获取类型    
        ov := reflect.ValueOf(o) //获取值    
        fmt.Println(ot, "\n")    
        fmt.Println(ov, "\n")    
        fmt.Println(ot.Name(), "\n")//打印这个实现了空接口的结构名称    
        for i := 0; i < ot.NumField(); i += 1 { //获取这个结构体内的值        
        n := ot.Field(i)        
        val := ov.Field(i)        
        fmt.Println(n.Type, ":", n.Name, ",", val)   
         }
     for i := 0; i < ot.NumMethod(); i += 1 { //打印这个结构体的每个方法        
        f := ot.Method(i)        
        fmt.Printf("%s:%v,%v\n", f.Name, f.Type, f.Index)    
        }
}
func Setname(o interface{}) { //通过反射设置值    
    v := reflect.ValueOf(o)    
    fmt.Println(v.Elem())          //这里打印出来是这个结构体    
    fmt.Println(v.Elem().CanSet()) //这里返回的是个布尔    
    fmt.Println(v.Kind())          //这里打印出来的就是ptr    
    fmt.Println(reflect.Ptr)       //也是ptr,引出个问题,为什么不用字符串"ptr"?以后再找答案,指针    
    fmt.Println(v)    //Elem返回v持有的接口保管的值的Value封装,    
    //或者v持有的指针指向的值的Value封装。如果v的Kind不是Interface或Ptr会panic;如果v持有的值为nil,会返回Value零值。    
    //Kind返回v持有的值的分类,如果v是Value零值,返回值为Invalid    
    if v.Kind() == reflect.Ptr && !v.Elem().CanSet() { //如果是指针且不能被修改        
        fmt.Println("xxx") //这个判断有问题,如果不是指针也会走else,或者可以修改但不是指针也会走else        
        return    
        } else {        
        v = v.Elem()    
        }    
    n := v.FieldByName("Name")    
    if n.IsValid() && n.Kind() == reflect.String { //如果取到了值并且类型是字符串则修改        
        fmt.Println(n, "\n", n.Kind())        
        n.SetString("lele") //修改名字//通过反射对值进行修改,肯定可以修改拉,传进来的是指针    
        }
}

原文链接:反射reflection-GOLANG

上一篇下一篇

猜你喜欢

热点阅读