反射的应用-结构体类型转换

未匹配的标注

结构体类型转换

与前面的测试类似的思路,将结构体类型Student转成Interface,再获取其reflect.Type类型和reflect.Value类型。结合Value的方法使用变量,最后将reflect.Value类型转成 interface,再通过类型断言,转成原始的Student类型。

主要体会“断言”在转换过程中的重要性。

type Student struct {
   Id int
   Name string
   Age int
}

func reflectTest(i interface{})  {
   // 获取变量的 reflect.Type
   reType := reflect.TypeOf(i)
   fmt.Println("reflect.Type=", reType)

   // 获取变量的 reflect.Value
   reVal := reflect.ValueOf(i)
   fmt.Println("reflect.Value=", reVal)

   // 打印reVal类型,使用 reVal,打印Name 成员 失败。无法索引Name成员
   //fmt.Printf("reVal=%T, name=%v",reVal,  reVal.Name)

   // 将 reVal 转成 interface
   iVal := reVal.Interface()
   fmt.Printf("iVal= %v, type= %T\n", iVal, iVal)
   // iVal.Name 会报错Unresolved reference 'Name'
   // fmt.Printf("iVal= %v, type= %T, name= %v\n", iVal, iVal, iVal.Name)

   // 将 interface 通过类型断言 转回成 Student
    // stu:= iVal.(Student)
    if stu, ok := iVal.(Student); ok {
        fmt.Printf("stu= %v, type= %T, name=%v\n", stu, stu, stu.Name)
    }
}

func main() {
   // 创建一个结构体对象
   stu := Student{9527, "Andy", 18}

   // 调用反射测试函数
   reflectTest(stu)
}

与int类型类似的,reflect.ValueOf(i) 返回的reVal 的值打印是结构体的成员信息。而使用fmt.Printf() 的%T 去查看reVal 的类型,发现它依然是reflect.Value类型。因此,是不能直接使用 reVal 去索引它的成员 Name的。使用iVal := reVal.Interface(),将其转换为interface。可以索引Name吗?依然不行,会显示错误:Unresolved reference 'Name'

这里强调!反射的本质是运行时进行调动的一种机制。虽然运行时,iVal的的确确是一个Student 结构体对应的类型,但编译时,编译器失无法确认的。

因此!必须使用类型断言!!转成具体类型,才能索引成员变量Name。

// 将 interface 通过类型断言 转回成 Student
stu := iVal.(Student)
fmt.Printf("stu= %v, type= %T, name= %v\n", stu, stu, stu.Name)

输出结果:stu= {9527 Andy 18}, type= main.Student, name= Andy
当然,为了确保断言成功,我们可以添加判断机制:

// 将 interface 通过类型断言 转回成 Student
//stu:= iVal.(Student)
if stu, ok := iVal.(Student); ok {
   fmt.Printf("stu= %v, type= %T, name= %v\n", stu, stu, stu.Name)
}

本文章首发在 LearnKu.com 网站上。

上一篇 下一篇
讨论数量: 0
发起讨论 只看当前版本


暂无话题~