加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

(四十五)golang--反射

发布时间:2020-12-16 09:17:52 所属栏目:大数据 来源:网络整理
导读:反射基本介绍: (1)反射可以在运行时动态获取变量的各种信息,比如变量的类型、类别; (2)如果是结构体变量,还可以获取结构体本身的信息(包括结构体字段、方法); (3)通过反射,可以修改变量的值,可以调用关联的方法; (4)使用反射,需要Import

反射基本介绍:

(1)反射可以在运行时动态获取变量的各种信息,比如变量的类型、类别;

(2)如果是结构体变量,还可以获取结构体本身的信息(包括结构体字段、方法);

(3)通过反射,可以修改变量的值,可以调用关联的方法;

(4)使用反射,需要Import "reflect:"

变量--空接口--relect.Value之间的转换关系:

int变量与反射变量之间的转换:

package main

import (
    "fmt"
    reflect"
)

func reflectTest(b interface{}) {
    rTyp := reflect.TypeOf(b)
    fmt.Printf(rTyp=%v,type=%Tn,rTyp,rTyp)
    rVal := reflect.ValueOf(b)
    fmt.Printf(rVal=%v,rVal,rVal)

    iVal := rVal.Interface()
    num2 := iVal.(int)
    fmt.Printf(num2=%v,num2,num2)
}

func main() {
    var num int = 100
    reflectTest(num)
}

?结构体变量与反射变量之间的转换:

type student struct {
    name string
    age  
}

func reflectTest02(b  rVal.Interface()
    stu2 := iVal.(student)
    fmt.Printf(stu2=%v,stu2,stu2)
    fmt.Printf(name:%v,age:%v student{
        name: tom20

反射注意事项和使用细节:
(1)reflect.Vale.Kind,获取变量的类别,返回的是一个常量;

(2)Type是类型,Kind是类别,Type和Kind可能是相同的,也可能是不同的;

比如:var num int=10的type是Int,Kind也是int

   ? var stu Student, stu的rype是pkg1.Student,Kind是struct

(3)通过反射介意让变量在interface{}和reflect.Value之间相互转换;

(4)使用反射的方式来获取变量的值,要求数据类型匹配;

(5)通过反射来修改变量,注意当使用SetXxx方法来设置需要通过对指针类型来完成,这样才能改变传入变量的值,同时需要使用到reflect.Value.Elem()方法;即rVal.Elem().SetInt(20)

具体实践;

使用反射来遍历结构体的字段,并调用结构体的方法,并获取结构体标签的值。


)

type monster  {
    Name  string `json:name`
    Age   int    `json:monster_age`
    Score float32
    Sex   
}

func (m monster) Print() {
    fmt.Println(----strat----)
    fmt.Println()
    fmt.Println(----end----)
}

func (m monster) GetSum(n1,n2 int)  {
    return n1 + n2
}

func (m monster) Set(name string,age int,score float32,sex ) {
    m.Name = name
    m.Age = age
    m.Score = score
    m.Sex = sex
}

func testStruct(b {}) {
    //获得类型
    rtyp := reflect.TypeOf(b)
    获得值
    rval := reflect.ValueOf(b)
    获得类别
    kd := rval.Kind()
    如果kd不是指针类型且rval.Elem()不是结构体类别
    if kd != reflect.Ptr && rval.Elem().Kind() == reflect.Struct {
        fmt.Println(expect struct)
        return
    }
    获取结构体有几个字段
    num := rval.Elem().NumField()
    fmt.Printf(struct has %d fieldsn遍历每个字段
    for i := 0; i < num; i++ {
        输出该字段的值
        fmt.Printf(field %d:值为=%vn获取该字段的json标签
        tagval := rtyp.Elem().Field(i).Tag.Get(json如果标签不为空,则打印出标签
        if tagval != "" {
            fmt.Printf(field %d:tag为=%vn0).SetString(孙悟空)
    获取结构体有几个方法
    numOfMethod := rval.Elem().NumMethod()
    fmt.Printf(struct has %d methodsn获取第二个方法,函数的顺序是按首字母的ACSII进行排序的,所以这里第二个方法是Print
    rval.Elem().Method(1).Call(nil)
    定义一个reflect.Value切片
    var params []reflect.Value
    添加两个整型
    params = append(params,reflect.ValueOf(10))
    40调用第一个方法,并传入参数(注意参数类型是reflect.Value切片)
    res := rval.Elem().Method(0).Call(注意res是一个切片,里面只有一个值
    fmt.Println(res=",res[0].Int())

}

func main() {
    var a monster = monster{
        Name:  40020.9a)
    fmt.Println(a)
}

要在反射中修改结构体的字段的值,必须传入的是地址,并且在反射中使用.Elem().SetXxx()

具体实践2:通过反射完成适配器

func main() {
    test1 := func(v1 ) {
        fmt.Printf(v1=%d,v2=%dn= func(call interface{},args ...{}) {
        获取参数长度
        n := len(args)
        定义参数切片
        params := make([]reflect.Value,n)
        将参数存入到切片中
        0; i < n; i++ {
            params[i] = reflect.ValueOf(args[i])
        }
         for i := 0; i < n; i++ {
             fmt.Println(args[i])
         }
        获取函数名
        function := reflect.ValueOf(call)
        将参数传给函数,并调用函数
        function.Call()
    }

    bridge(test1,1,2)
    bridge(test2,1)">2,1)">test2)

}

运行结果:

具体实践3:通过反射操作任意结构体类型

type user  {
    UserID 
    Name   
}

func testReflectStruct() {
    var (
        model *user
        sv    reflect.Value
    )
    model = &user{}
    sv = reflect.ValueOf(model)
    这里是指针类别
    fmt.Println(sv.Kind().String())
    sv = sv.Elem()
    这里是结构体类别
    fmt.Println(sv.Kind().String())
    sv.FieldByName(UserID").SetString(1)
    sv.FieldByName(Name)
    fmt.Println(model)
}

?

?

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读