go语言反射

作者: 程序员小饭 | 来源:发表于2019-07-18 15:59 被阅读0次

反射的特点

  • 反射功能具有强大的功能
  • 反射是用程序检查其所拥有的结构,尤其是类型的一种能力
  • 是元编程的一种形式
  • 我们可以在【运行时】通过反射来分析一个结构体
  • 检查其类型和变量(类型和取值)和方法
  • 动态的修改变量和调用方法
  • 这对于没有源代码的包尤其有用
  • 这是一个强大的工具,除非真的有必要,否则应当避免使用或者小心使用

反射API

TypeOf

oType := reflect.TypeOf(obj)
t.Name()
kind := oType.Kind()
    kind:struct 系统类型的枚举
    type: 具体的类
t.NumField()
t.NumMethod()
structField := oType.Field(i)
    structField.Name
    structField.Type

method := oType.Method(i)
    methodType := methodType
        argNum := method.Type.NumIn()  参数个数
        artType := method.Type.In(0)  第1个参数类型
t.FieldByIndex([]int{0, 1})
    找出第0个父结构体中的第1个属性

ValueOf

oValue := reflect.ValueOf(obj)
field := oValue.Field(i) -> fieldValue :=value.Field(i).Interface{}(获取第i个属性的值的“正射”形式)

fieldValue := value.FieldByIndex([]int{0, 0}).Interface()  找出第0个父结构体中的第0个属性值


oPtrValue.Elem() 获取地址value中的值value

oPtrValue.Elem().CanSet()  检查当前地址value内的值是否可以改变(可改变条件:可寻址+不来字非导出字段)

 oPtrValue.Elem().SetInt(999)

 value.SetString("jack")

 nameValue := value.FieldByName("Name")


 isVaild := value.IsVaild()  nil(0值)非法  非常罕见

 kind := value.Kind()和type.Kind()一样
 mathod := oValue.Method(i)   通过方法的值可以调取方法
 methodValue.Call([]reflect.Value{val1,val2})

代码实例(简单类型的反射操作)

package main
import (
    "fmt"
    "reflect"
)
//简单类型的反射
func reflectTest01(b interface{}) {
    //通过反射来获取传入变量的   type,kind。值
    //1.先获取到reflect.Type
    rType := reflect.TypeOf(b)
    fmt.Println("rType = ", rType)
    //2.获取到reflect.Value
    rVal := reflect.ValueOf(b)
    n2 := 2 + rVal.Int()

    fmt.Println("n2 = ", n2)
    fmt.Printf("rVal = %v, rVal type=%T\n", rVal, rVal)
    //下面我们将rVal转换成interface
    iv := rVal.Interface()
    //将interface通过断言转换成需要的类型
    num2 := iv.(int)
    fmt.Println("num2 = ", num2)
}

//复杂类型的反射
func reflectTest02(b interface{}) {
    //通过反射获取到传入变量的type  kind值
    rType := reflect.TypeOf(b)
    fmt.Println("rType =", rType)

    //获取到reflectValue
    rVal := reflect.ValueOf(b)

    //获取变量对应的kind
    typeKind := rType.Kind()
    valKind := rVal.Kind()
    fmt.Printf("typeKind = %v, valKind = %v\n", typeKind, valKind)

    //将rVal转换为interface{}
    iv := rVal.Interface()
    fmt.Printf("iv = %v is type =%T\n", iv, iv)
    //把interface{}通过断言转换成需要的类型
    stu, ok := iv.(Student)
    if ok {
        fmt.Println("stu.Name = ", stu.Name)
    }
}
func changeValue(b interface{}) {
    rVal := reflect.ValueOf(b)
    fmt.Printf("rVal kind =%v\n", rVal.Kind())
    rVal.Elem().SetInt(1)
}

type Student struct {
    Name string
    Age  int
}

func main() {
    var b int = 10
    reflectTest01(b)
    fmt.Println("-------------")

    stu := Student{
        Name: "tom",
        Age:  12,
    }
    reflectTest02(stu)
    fmt.Println("-------------")
    var c int = 100
    changeValue(&c)
    fmt.Println(c)
}

反射操作相关代码(结构体)

package main
import (
    "fmt"
    "reflect"
)
type Monster struct {
    Name  string `json:"name"`
    Age   int    `json:"age"`
    Score float32
    Sex   string
}

func (s Monster) Print() {
    fmt.Println("-----start-------")
    fmt.Println(s)
    fmt.Println("-----end-------")
}
func (s Monster) GetSum(n1, n2 int) int {
    return n1 + n2
}
func (s Monster) Set(name string, age int, score float32, sex string) {
    s.Name = name
    s.Age = age
    s.Score = score
    s.Sex = sex
}

func TestStruct(a interface{}) {
    rType := reflect.TypeOf(a)
    rVal := reflect.ValueOf(a)
    kd := rVal.Kind()
    if kd != reflect.Struct {
        fmt.Println("expect struct")
        return
    }
    num := rVal.NumField()
    fmt.Println("struct fields:", num)
    //变量结构体的所有字段
    for i := 0; i < num; i++ {
        fmt.Printf("field %d:值为:%v\n", i, rVal.Field(i))
        tagVal := rType.Field(i).Tag.Get("json")
        if tagVal != "" {
            fmt.Printf("field %d: tag为=%v\n", i, tagVal)
        }
    }

    //结构体的方法操作
    numOfMethod := rVal.NumMethod()
    fmt.Printf("struct has %d methods\n", numOfMethod)

    //var params []reflect.Value
    rVal.Method(1).Call(nil)

    //调用结构体的第1个方法Method(0)
    var params []reflect.Value
    params = append(params, reflect.ValueOf(10))
    params = append(params, reflect.ValueOf(40))
    res := rVal.Method(0).Call(params)
    fmt.Println("res = ", res[0].Int())
    //反射修改字段

}
func main() {
    var a Monster = Monster{
        Name:  "tom",
        Age:   100,
        Score: 30.1,
        Sex:   "男",
    }
    TestStruct(a)
}


相关文章

  • golang 反射机制

    go语言也有反射机制,今天自学到go的反射,发现还是很值得记录一些这个知识点的。go语言它是通过 reflect ...

  • Golang 学习笔记十四 反射

    参考《快学 Go 语言》第 15 课 —— 反射反射是 Go 语言学习的一个难点,但也是非常重要的一个知识点。反射...

  • go语言 反射

    为何需要反射? 下面例子试图打印出传入的interface值,无法找到无尽的未知类型的表示方式,我们被卡住了。这就...

  • go语言反射

    反射的特点 反射功能具有强大的功能 反射是用程序检查其所拥有的结构,尤其是类型的一种能力 是元编程的一种形式 我们...

  • Go语言反射

    【转】https://www.cnblogs.com/itbsl/p/10551880.html[https://...

  • 什么是amino编码

    1. Reflect反射 1.1 关于go的reflect 现代通用编程语言中,有的语言支持反射,有的不支持。并且...

  • Go语言基础——反射

    Go语言提供了一种机制,在编译时不知道类型的情况下,在运行时,可更新变量、查看值、调用方法以及直接对它的结构成员进...

  • Go语言之反射

    来自本人公众号:灰子学技术原文链接:https://mp.weixin.qq.com/s/SBqx0theCm-G...

  • go语言的反射

    首先我们知道go语言的变量,其包括两部分,一个为类型(type),一个为值(value),我们回想一下接口的具体实...

  • Go语言反射规则

    原文地址:http://blog.golang.org/laws-of-reflection 介绍 反射在计算机的...

网友评论

    本文标题:go语言反射

    本文链接:https://www.haomeiwen.com/subject/fymllctx.html