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

相关推荐
禹曦a10 分钟前
JavaScript性能优化实战指南
开发语言·javascript·性能优化
AAA修煤气灶刘哥13 分钟前
ES 地理查询玩明白,产品要的 “附近的店” 再也难不倒我!(附 DSL+Java 实战)
java·后端·elasticsearch
Swift社区14 分钟前
Swift 解法详解:LeetCode 371《两整数之和》
开发语言·leetcode·swift
Swift社区16 分钟前
Swift 解法详解 LeetCode 362:敲击计数器,让数据统计更高效
开发语言·leetcode·swift
ytttr87320 分钟前
PHP中各种超全局变量使用的过程
开发语言·php
shark_chili23 分钟前
深入理解CPU缓存:编写高性能Java代码的终极指南
后端
Q741_14726 分钟前
C++ 前缀和 高频笔试考点 实用技巧 牛客 DP34 [模板] 前缀和 题解 每日一题
开发语言·c++·算法·前缀和·牛客网
十八旬31 分钟前
苍穹外卖项目实战(day-5完整版)-记录实战教程及问题的解决方法
java·开发语言·spring boot·redis·mysql
金銀銅鐵1 小时前
[Java] 枚举常量的精确类型一定是当前枚举类型吗?
java·后端