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

相关推荐
ChinaRainbowSea6 小时前
5. Prompt 提示词
java·人工智能·后端·spring·prompt·ai编程
郝学胜-神的一滴6 小时前
现代C++ Lambda表达式:最佳实践、深入理解和资源推荐
开发语言·c++·程序人生·软件工程
IT_陈寒6 小时前
Vue3性能优化实战:这5个技巧让我的应用加载速度提升70%
前端·人工智能·后端
Apifox6 小时前
Apifox 9 月更新| AI 生成接口测试用例、在线文档调试能力全面升级、内置更多 HTTP 状态码、支持将目录转换为模块
前端·后端·测试
一口面条一口蒜7 小时前
R语言中的S3 泛型与方法
开发语言·r语言
_OP_CHEN7 小时前
C++基础:(五)类和对象(下)—— static、友元和内部类
开发语言·c++·构造函数·static成员·友元·匿名对象·编译器优化
databook7 小时前
Manim实现闪电特效
后端·python·动效
yongui478347 小时前
基于MATLAB的8QAM调制解调仿真与BER性能分析
开发语言·matlab
小哈里7 小时前
【后端开发】golang部分中间件介绍(任务调度/服务治理/数据库/缓存/服务通信/流量治理)
数据库·缓存·中间件·golang·后端开发
我不是混子7 小时前
什么是Java 的 Lambda 表达式?
java·后端