美文网首页
29.Go语言·反射·基本介绍

29.Go语言·反射·基本介绍

作者: 一枼落知天下 | 来源:发表于2019-06-13 12:11 被阅读0次

main.go

// Go语言·反射
package main


import (
    model "day33/model"
)

var content string = `
————————————————Go语言·反射————————————————————
一、反射
    应用场景:
        结构体tag——对结构体序列化
        编写函数的适配器,桥连接
    介绍:
        反射可以在运行时动态获取变量的各种信息。
            比如:变量的类型type,类别kind
        结构体变量,可以获取到结构体本身的信息
            包含结构体的字段、方法
        通过反射,可以修改变量的值,可以调用关联的方法
        使用反射:import "reflect"
    1.reflect.TypeOf(变量名),获取变量的类型,返回reflect.Type类型
    2.reflect.ValueOf(变量名),可以获取变量的值,返回reflect.Value类型的结构体
    通过reflect.Value,可以获取到关于该变量的很多信息。
二、注意事项
    1.reflect.Value.Kind 获取变量类别,返回一个常量
    2.Type是类型,Kind是类别,Type和Kind可能是相同的,
    也可能是不相同的
        比如:var num int = 10 num的Type是int,Kind也是int
        比如:var stu Student 
            stu的Type是main.Student或model.Student
            stu的Kind是Student
    3.通过反射可以让变量在interface{}和reflect.Value之间相互转换
        变量<=>interface{}<=>reflect.Value
    4.使用反射的方式获取变量的值并返回对应的类型,必须数据类型匹配
        比如:var x int = 10 
        应该用 reflect.Value(x).Int() 而不能用其他的,否则报panic
    5.通过反射的来修改变量,注意当使用SetXxx方法来设置需要通过对应的
    指针来完成,这样才能改变传入的变量的值。同时需要使用到reflect.Value.Elem()
        reflectVal := reflect.ValueOf(b)
        reflectVal.Elem().SetInt(100)
    6.func (v Value) Elem() Value
    Elem返回v持有的接口保管的值的Value封装,或者v持有的指针指向的值的Value封装。
    如果v的Kind不是Interface或Ptr会panic;如果v持有的值为nil,会返回Value零值。
三、反射的最佳实践
    1.使用反射来遍历结构体的字段,调用结构体的方法,并获取结构体标签的值

`



func main() {
    model.Go()
}

model/utils.go

package model

import (
    "fmt"
    "reflect"
)

type Student struct {
    Name string
    Age int
}


func Going(){
    var num int = 10
    reflectModifyBaseDta(&num)
    fmt.Println("num=",num)
}


// 基本数据类型<=>interface{}<=>reflect.Value
// var num int = 100
// reflectBaseDta(num)
func reflectBaseDta(b interface{}) {
    // 通过反射获取传入的变量的type,kind,值

    // 1.获取到 reflect.Type 类型
    reflectType := reflect.TypeOf(b)
    // reflectType的值:int,reflectType的类型:*reflect.rtype
    fmt.Printf("reflectType的值:%v,reflectType的类型:%T \n",
        reflectType,reflectType)

    // 2.获取到 reflect.Value 类型
    reflectVal := reflect.ValueOf(b)
    // reflectVal的值:100,reflectVal的类型:reflect.Value
    fmt.Printf("reflectVal的值:%v,reflectVal的类型:%T \n",
        reflectVal,reflectVal)

    // 3.将reflectVal---》转成 interface{}
    interfaceVal := reflectVal.Interface()

    // 4.通过断言--》int数据类型
    intVal := interfaceVal.(int)

    // intVal的值:100,intVal的类型:int
    fmt.Printf("intVal的值:%v,intVal的类型:%T \n",
        intVal,intVal)
}

/**
 * [reflectStructDta ]
 * 结构体<=>interface{}<=>reflect.Value
 * @author Jhou Shuai
 * @datetime 2019-06-12T14:57:45+0800
 * stu := Student {
        Name:"Faker",
        Age:19,
    }
    reflectStructDta(stu)
 */
func reflectStructDta(b interface{}) {
    

    // 1.获取到 reflect.Type 类型
    reflectType := reflect.TypeOf(b)
    // reflectType的值:model.Student,reflectType的类型:*reflect.rtype
    fmt.Printf("reflectType的值:%v,reflectType的类型:%T \n",reflectType,reflectType)

    // 2.获取到 reflect.Value 类型
    reflectVal := reflect.ValueOf(b)
    // reflectVal的值:{Faker 19},reflectVal的类型:reflect.Value
    fmt.Printf("reflectVal的值:%v,reflectVal的类型:%T \n",reflectVal,reflectVal)

    // 通过反射获取传入的变量的type,kind,值
    // 1.reflectType.Kind() ===>
    // 2.reflectVal.Kind()  ===>
    fmt.Printf("变量的kind:%v,reflectType的类型:%T \n",reflectType.Kind(),reflectType)



    // 3.将reflectVal---》转成 interface{}
    interfaceVal := reflectVal.Interface()
    // interfaceVal的值:{Faker 19},interfaceVal的类型:model.Student
    fmt.Printf("interfaceVal的值:%v,interfaceVal的类型:%T \n",interfaceVal,interfaceVal)
    // 4.通过断言--》结构体
    // switch interfaceVal.(type) {
    //  case
    // }
    structDta,ok := interfaceVal.(Student)
    if ok{
        fmt.Printf("structDta.Name的值:%v \n",structDta.Name)
    }
}

/**
 * [reflectModifyDta 修改值]
 * @author Jhou Shuai
 *  var num int = 10
    reflectModifyBaseDta(&num)
    fmt.Println("num=",num)
 * @datetime 2019-06-12T18:13:37+0800
 */
func reflectModifyBaseDta(b interface{}){
    reflectVal := reflect.ValueOf(b)
    // reflectVal的值:0xc00006a080,
    // reflectVal的类型:reflect.Value,
    // reflectVal的类别:ptr
    fmt.Printf("reflectVal的值:%v,reflectVal的类型:%T,reflectVal的类别:%v \n",reflectVal,reflectVal,reflectVal.Kind())
    
    reflectVal.Elem().SetInt(100)
}



/**
 * [TypeJudge 类型断言]
 * @author Jhou Shuai
 * @datetime 2019-06-12T15:11:32+0800
 */
func TypeJudge(items ...interface{}) {
    for index ,value := range items {
        switch value.(type){
            case bool:
                fmt.Printf("第%v个参数是bool类型,值:%v \n",index,value)
            case float32:
                fmt.Printf("第%v个参数是float32类型,值:%v \n",index,value)
            case int,int8,int16,int32,int64:
                fmt.Printf("第%v个参数是整数类型,值:%v \n",index,value)
            case string:
                fmt.Printf("第%v个参数是string类型,值:%v \n",index,value)
            case Student:
                fmt.Printf("第%v个参数是Student类型,值:%v \n",index,value)
            case *Student:
                fmt.Printf("第%v个参数是*Student类型,值:%v \n",index,value)
            default:
                fmt.Printf("第%v个参数是类型不确定,值:%v \n",index,value)
        }
    }
}

相关文章

网友评论

      本文标题:29.Go语言·反射·基本介绍

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