Golang学习笔记-反射

土豆吞噬者 · · 558 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

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

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<valueType.NumField();i++{
        field:=valueType.Field(i)
        fmt.Println(field.Name,field.Type)
    }
    //遍历结构体导出的方法
    for i:=0;i<valueType.NumMethod();i++{
        method:=valueType.Method(i)
        fmt.Println(method.Name)
    }
    //遍历函数参数和返回值
    valueType=reflect.TypeOf(Person{}.AddHeight)
    for i:=0;i<valueType.NumIn();i++{
        arg:=valueType.In(i)
        fmt.Println(arg)
    }
    for i:=0;i<valueType.NumOut();i++{
        result:=valueType.Out(i)
        fmt.Println(result)
    }

}

底层类型

使用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学习笔记-反射

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

558 次点击  
加入收藏 微博
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传