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

未匹配的标注

结构体类型转换#

与前面的测试类似的思路,将结构体类型 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 网站上。

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


暂无话题~