上一篇介绍了变量中的pair,这一篇文章开始介绍变量中的

反射reflect包

反射的定义

反射可以对一个已知变量,可以动态的获得当前变量的type和value。

reflect.valueOf接口

valueOf用来获取输入参数接口中的数据的。如果接口为空则返回0

// ValueOf returns a new Value initialized to the concrete value
// stored in the interface i. ValueOf(nil) returns the zero Value.
func ValueOf(i interface{}) Value {
    if i == nil {
        return Value{}
    }

    // TODO: Maybe allow contents of a Value to live on the stack.
    // For now we make the contents always escape to the heap. It
    // makes life easier in a few places (see chanrecv/mapassign
    // comment below).
    escapes(i)

    return unpackEface(i)
}

reflect.typeOf接口

typeOf用来动态获取输入参数接口中的值的数据类型,如果接口为空则返回nil。

// TypeOf returns the reflection Type that represents the dynamic type of i.
// If i is a nil interface value, TypeOf returns nil.
func TypeOf(i interface{}) Type {
    eface := *(*emptyInterface)(unsafe.Pointer(&i))
    return toType(eface.typ)
}

例题1:使用reflect获取简单变量的pair

package main

import (
    "fmt"
    "reflect"
)

// 该函数使用reflect包将传入的变量的type和value打印出来
func reflectNum(arg interface{}) {
    fmt.Println("type: ", reflect.TypeOf(arg)) // 使用reflect包,打印出传递过来的变量的数据类型
    fmt.Println("value: ", reflect.ValueOf(arg)) // 使用reflect包,打印出传递过来的变量的值
}

func main() {
    var num float64 = 1.2345 // 声明一个浮点变量

    reflectNum(num) // 调用函数
}

运行结果:
image.png

例题2:使用reflect获取复杂数据类型的变量的pair

reflect获取结构体的数据类型和值

package main

import (
    "fmt"
    "reflect"
)

type User struct {
    Id int
    Name string
    Age int
}

func (this *User) Call() {
    fmt.Println("user is called ..")
    fmt.Printf("%v\n", this) // 打印变量的默认格式
}

func DoFiledAndMethod(input interface{}) {
    // 获取input的type
    inputType := reflect.TypeOf(input)
    // 获取Name属性所在的结构体名
    fmt.Println("inputType is :", inputType.Name())
    
    // 获取input的value
    inputValue := reflect.ValueOf(input)
    // 打印获取到的input的真实值
    fmt.Println("inputValue is:", inputValue)
}

func main() {
    user := User{1, "peiqi", 18} // 实例化一个结构体

    DoFiledAndMethod(user) // 调用函数
}

运行结果:
image.png
可以看到通过reflect可以获得到结构体的Type以及结构体的Value

reflect获取结构体所绑定的方法和方法对应的类型

  • 获取思路如下:

      1. 获取interface的reflect.Type,通过Type得到numField(结构体内的属性称为numfield),进行遍历
      1. 得到每一个field(结构体的每一个属性称为一个field),获得数据类型
      1. 通过field有一个interface()方法得到对应的value
package main

import (
    "fmt"
    "reflect"
)

type User struct {
    Id int
    Name string
    Age int
}

func (this User) Call() {
    fmt.Println("user is called ..")
    fmt.Printf("%v\n", this) // 打印变量的默认格式
}

func DoFieldAndMethod(input interface{}) {
    // 获取input的type
    inputType := reflect.TypeOf(input)
    fmt.Println("inputType is :", inputType.Name())
    // 获取input的value
    inputValue := reflect.ValueOf(input)
    fmt.Println("inputValue is:", inputValue)    

    // 通过type 获取里面的方法,调用
    for i := 0; i < inputType.NumMethod(); i++ {
        m := inputType.Method(i)
        fmt.Printf("%s: %v\n", m.Name, m.Type)
    }
}

func main() {
    user := User{1, "peiqi", 18} // 实例化一个结构体

    DoFieldAndMethod(user) // 调用函数
}

运行结果:
image.png
可以看到通过反射,可以获得实例对象的方法名和方法对应的类型。

详细反射接口可以多看看官方文档。

最后修改:2024 年 03 月 13 日
如果觉得我的文章对你有用,请随意赞赏