Go 第14章 断言Assertion和反射reflect Go 第14章 断言Assertion和反射reflect

2023-09-25

一、断言

把一个接口类型指定为它原始的类型

package main

import "fmt"

type User struct {
   Name string
   Age  int
}

type Student struct {
   Class string
   User
}

func main() {
   s := Student{"三年二班", User{}}
   u := User{
      Name: "鲁鲁槟",
      Age:  18,
   }
   check(s)
   check(u)
}

func check(v interface{}) {
   switch v.(type) {
   case User:
      fmt.Println(v.(User).Name)
   case Student:
      fmt.Println(v.(Student).Class)
   }
}

二、反射

  • 在编译时不知道类型的情况下,可更新变量、运行时查考值、调用方法以及直接对他们的布局进行操作的机制

  • 通俗一点就是可以知道本数据的原始数据类型和数据内容、方法等,并且可以进行一定操作

为什么要使用反射

  • 我们通过接口或者其他的方式接收到了类型不固定的数据的时候需要写太多的 swatch case 断言代码,此时代码不灵活且通用性差,反射这时候就可以无视类型改变原数据结构中的数据

reflect 包

  • reflect.ValueOf():获取输入参数接口中的数据的值

  • reflect.TypeOf():动态获取输入参数接口中的值的类型

  • reflect.TypeOf().Kind():用来判断类型

  • reflect.ValueOf().Field(int):用来获取值

  • reflect.FieldByIndex([]int{0,1}):层级取值

  • reflect.ValueOf().Elem():获取原始数据并操作

reflect.ValueOf():获取输入参数接口中的数据的值

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Name string
   Age  int
}

type Student struct {
   Class string
   User
}

func main() {
   u := User{
      Name: "鲁鲁槟",
      Age:  18,
   }
   s := Student{"三年二班", u}
   check(s)
}

func check(i interface{}) {
   v := reflect.ValueOf(i)
   fmt.Println(v)    
}

reflect.TypeOf():动态获取输入参数接口中的值的类型

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Name string
   Age  int
}

type Student struct {
   Class string
   User
}

func main() {
   u := User{
      Name: "鲁鲁槟",
      Age:  18,
   }
   s := Student{"三年二班", u}
   check(s)
}

func check(i interface{}) {
   t := reflect.TypeOf(i)
   fmt.Println(t)
}

reflect.TypeOf().Kind():用来判断类型

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Name string
   Age  int
}

type Student struct {
   Class string
   User
}

func main() {
   u := User{
      Name: "鲁鲁槟",
      Age:  18,
   }
   s := Student{"三年二班", u}
   check(s)
}

func check(i interface{}) {
   t := reflect.TypeOf(i)
   fmt.Println(t.Kind())
   fmt.Println(reflect.Struct)
}

reflect.ValueOf().Field(int):用来获取值

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Name string
   Age  int
}

type Student struct {
   Class string
   User
}

func main() {
   u := User{
      Name: "鲁鲁槟",
      Age:  18,
   }
   s := Student{"三年二班", u}
   check(s)
}

func check(i interface{}) {
   t := reflect.TypeOf(i)
   v := reflect.ValueOf(i)
   for i := 0; i < t.NumField(); i++ {
      fmt.Println(v.Field(i))
   }
}

reflect.FieldByIndex([]int{0,1}):层级取值

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Name string
   Age  int
}

type Student struct {
   Class string
   User
}

func main() {
   u := User{
      Name: "鲁鲁槟",
      Age:  18,
   }
   s := Student{"三年二班", u}
   check(s)
}

func check(i interface{}) {
   v := reflect.ValueOf(i)
   fmt.Println(v.FieldByIndex([]int{0}))
   fmt.Println(v.FieldByIndex([]int{1}))
   fmt.Println(v.FieldByIndex([]int{1, 0}))
   fmt.Println(v.FieldByName("Class"))
}

reflect.ValueOf().Elem():获取原始数据并操作

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Name string
   Age  int
}

type Student struct {
   Class string
   User
}

func main() {
   u := User{
      Name: "鲁鲁槟",
      Age:  18,
   }
   s := Student{"三年二班", u}
   check(&s)
   fmt.Println(s)
}

func check(i interface{}) {
   v := reflect.ValueOf(i)
   e := v.Elem()
   fmt.Println(e)
   e.FieldByName("Class").SetString("四年二班")
   fmt.Println(i)
}

reflect.ValueOf().Method()

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Name string
   Age  int
}

func (u User) SayName(name string) {
   fmt.Println("我的名字叫做", name)
}

func main() {
   u := User{
      Name: "鲁鲁槟",
      Age:  18,
   }
   check(u)
}

func check(i interface{}) {
   v := reflect.ValueOf(i)
   m := v.Method(0)
   m.Call([]reflect.Value{reflect.ValueOf("鲁鲁修")})
}
阅读 352