Golang学习笔记-反射

反射让我们可以在运行时获取对象的类型信息,比如查看一个结构体有多少字段,查看函数的入参类型和返回值类型等。

Go提供了reflect.TypeOf()和reflect.ValueOf获取任意对象的reflect.Value和reflect.Type,其中reflect.Type是一个接口类型,该接口提供了很多方法让我们获取类型信息,而reflect.Value是一个结构体,它提供了很多方法让我们获取或者写入reflect.Value结构体中存储的数据。

获取类型信息

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    name string
    height int
}

func (person Person) AddHeight(height int)  string{
    person.height+=height
    return string(person.height)
}

func main(){
    //遍历结构体字段
    person:=Person{}
    valueType:=reflect.TypeOf(person)
    for i:=0;i

底层类型

使用Kind方法可以获取类型的底层类型,Go提供了以下底层类型:

const (
    Invalid Kind = iota
    Bool
    Int
    Int8
    Int16
    Int32
    Int64
    Uint
    Uint8
    Uint16
    Uint32
    Uint64
    Uintptr
    Float32
    Float64
    Complex64
    Complex128
    Array
    Chan
    Func
    Interface
    Map
    Ptr
    Slice
    String
    Struct
    UnsafePointer
)

通过reflect.Value还原对象

使用Interface()方法可以将reflect.Value还原成接口类型,然后再强转一次就能还原成原本的类型。

func main(){
    value := reflect.ValueOf(1)
    fmt.Println(value.Interface().(int))
}

通过reflect.Value修改对象

如果想通过reflect.Value修改对象,那么reflect.ValueOf()需要传递对象的地址,然后通过Elem()方法找到这个指针指向的值才能修改,reflect.Value提供了CanSet()方法帮助我们判断是否可以修改该对象。

func main(){
    name:="xiongya"
    nameValue:=reflect.ValueOf(&name)
    nameValue.Elem().SetString("xy")
    fmt.Println(name)
}

动态调用方法

利用反射动态调用方法时参数和返回值都是reflect.Value切片。

package main

import (
    "fmt"
    "reflect"
    "strconv"
)

type Person struct {
    name string
    height int
}

func (person Person) AddHeight(height int)  string{
    person.height+=height
    return strconv.Itoa(person.height)
}

func main(){
    person:=Person{"xiao hong",100}
    value:=reflect.ValueOf(person)
    method:=value.MethodByName("AddHeight")
    if method.IsValid(){
        args:=[]reflect.Value{reflect.ValueOf(10)}
        fmt.Println(method.Call(args))
    }
}

你可能感兴趣的:(Golang学习笔记-反射)