go 反射 interface{} 判断类型 获取值 设置值 指针才可以设置值

内容包括

  1. 用interface{}接收值

  2. 判断interface{}的类型 switch

  3. 打印interface{}的类型

  4. 通过字符串对结构体,interface{}等进行设置值、获取值处理

示例代码

Go 复制代码
package main

import (
    "fmt"
    "log"
    "reflect"
)

type Student2 struct {
    Id1   int `json:"jsonTag1" db:"name2"`
    Name1 string
    age1  int
}

func reflectValue(a interface{}) {
    log.Println("================ reflect value start ==================")
    // 类型判断
    switch a.(type) {
    case float64:
       log.Println("a type is :", "float64")
    case float32:
       log.Println("a type is :", "float32")
    default:
       log.Println("a type is :", "default")
    }

    // 打印类型
    aType := reflect.TypeOf(a)
    log.Println("a type is:", aType)

    // 获取值
    aValue := reflect.ValueOf(a)
    log.Println("a value is :", aValue.Float())

    // 设置值报错,不传指针就没办法设置值
    // 报错信息:panic: reflect: reflect.Value.SetFloat using unaddressable value
    // aValue.SetFloat(32.11)
    // log.Println("a value is :", aValue.Float())

    log.Println("================ reflect value end ==================")
}

func reflectPoint(a interface{}) {
    log.Println("================ reflect point start ==================")

    // 打印类型
    aType := reflect.TypeOf(a)
    log.Println("a type is:", aType)

    // 判断类型
    aKind := aType.Kind()
    switch aKind {
    case reflect.Float64:
       log.Println("a kind is :", "float64")
    case reflect.Float32:
       log.Println("a kind is :", "float32")
    case reflect.Pointer:
       log.Println("a kind is :", "Pointer")
    }

    // 获取参数
    aValue := reflect.ValueOf(a)
    log.Println("a value is :", aValue.Elem().Float())

    // 设置参数
    aValue.Elem().SetFloat(32.1)
    log.Println("a value is :", aValue.Elem().Float())

    log.Println("================ reflect point end ==================")
}

func reflectStructValue(a interface{}) {
    log.Println("================ reflect struct value start ==================")

    // 获取类型
    aType := reflect.TypeOf(a)
    log.Println("a type of :", aType)
    log.Println("a type name :", aType.Name())

    // 获取值{100 name1 13}
    aValue := reflect.ValueOf(a)
    log.Println("a value of :", aValue)

    // 根据名称获取字段
    // 如果外边传的是value则没法赋值,如果传的是$stu地址 则可以复制
    name1Filed := aValue.FieldByName("Name1")
    if name1Filed.Kind() == reflect.String && name1Filed.CanSet() {
       name1Filed.SetString("name1111111111")
    }

    // 遍历属性
    fieldNum := aType.NumField()
    for i := 0; i < fieldNum; i++ {
       field := aType.Field(i)
       value := aValue.Field(i)
       // 这里得看属性是否大小写,如果小写没法子获取他的值
       // panic: reflect.Value.Interface: cannot return value obtained from unexported field or method
       // 获取字段标记:field.Tag.Get("json")
       if value.CanInterface() {
          log.Println("属性:", field.Name, field.Type, value.Interface(), field.Tag.Get("json"))
       } else {
          log.Println("属性:", field.Name, field.Type)
       }
    }

    // 遍历方法
    // func (stu Student2) Say()  可以获取到
    // func (stu *Student2) Say() aType.NumMethod就没法获取到了
    methodNum := aType.NumMethod()
    for i := 0; i < methodNum; i++ {
       method := aType.Method(i)
       log.Println("方法:", method.Name, method.Type)
    }

    // 根据名称获取方法,并执行
    sayMethod := aValue.MethodByName("Say")
    args := []reflect.Value{reflect.ValueOf("message1111")}
    sayMethod.Call(args)

    log.Println("================ reflect struct value end ==================")

}

func reflectStructPoint(a interface{}) {
    log.Println("================ reflect struct point start ==================")

    // 获取值{100 name1 13}
    aValue := reflect.ValueOf(a)
    log.Println("a value of :", aValue.Elem().Interface())

    // 根据名称获取字段
    // 如果外边传的是value则没法赋值,如果传的是$stu地址 则可以复制
    name1Filed := aValue.Elem().FieldByName("Name1")
    if name1Filed.Kind() == reflect.String && name1Filed.CanSet() {
       name1Filed.SetString("name1111111111")
    }
    log.Println("a value of :", a)
    log.Println("a value of :", aValue.Elem().Interface())

    log.Println("================ reflect struct point start ==================")
}

func (stu Student2) Say(message string) {
    log.Println("student say:", stu, message)
}

func main() {
    log.Println("main ...")
    var f float64 = 10
    // 传地址可以修改
    reflectPoint(&f)
    // 传值就不能修改
    reflectValue(f)

    stu := Student2{100, "name1", 13}
    stu.Say("1111")
    reflectStructValue(stu)
    reflectStructPoint(&stu)

    fmt.Println("success ...")
}

参考:

https://www.topgoer.com/常用标准库/反射.html

相关推荐
java1234_小锋19 分钟前
Spring IoC的实现机制是什么?
java·后端·spring
喵个咪29 分钟前
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:JWT 集成指南
后端·go
生骨大头菜41 分钟前
使用python实现相似图片搜索功能,并接入springcloud
开发语言·python·spring cloud·微服务
绝不收费—免费看不了了联系我43 分钟前
Fastapi的单进程响应问题 和 解决方法
开发语言·后端·python·fastapi
喵个咪1 小时前
开箱即用的 GoWind Admin|风行,企业级前后端一体中后台框架:OPA 集成指南:从原理到实践
后端·go
消失的旧时光-19431 小时前
深入理解 Java 线程池(二):ThreadPoolExecutor 执行流程 + 运行状态 + ctl 原理全解析
java·开发语言
咖啡续命又一天1 小时前
Trae CN IDE 中 Python 开发的具体流程和配置总结
开发语言·ide·python·ai编程
4311媒体网1 小时前
帝国cms调用文章内容 二开基本操作
java·开发语言·php
GSDjisidi1 小时前
东京IT软件会社-(株)GSD|多种技术栈募集,高度人才+20分
开发语言·面试·职场和发展
Victor3562 小时前
Netty(11) Netty的心跳机制是什么?为什么需要它?
后端