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

相关推荐
Blossom.1182 小时前
使用Python实现简单的人工智能聊天机器人
开发语言·人工智能·python·低代码·数据挖掘·机器人·云计算
da-peng-song2 小时前
ArcGIS Desktop使用入门(二)常用工具条——数据框工具(旋转视图)
开发语言·javascript·arcgis
galaxy_strive2 小时前
qtc++ qdebug日志生成
开发语言·c++·qt
TNTLWT2 小时前
Qt功能区:简介与安装
开发语言·qt
noravinsc3 小时前
redis是内存级缓存吗
后端·python·django
等等5433 小时前
Java EE初阶——wait 和 notify
java·开发语言
低代码布道师3 小时前
第五部分:第一节 - Node.js 简介与环境:让 JavaScript 走进厨房
开发语言·javascript·node.js
盛夏绽放3 小时前
Python字符串常用方法详解
开发语言·python·c#
{⌐■_■}3 小时前
【go】binary包,大小端理解,read,write使用,自实现TCP封包拆包案例
arm开发·tcp/ip·golang
noravinsc4 小时前
django中用 InforSuite RDS 替代memcache
后端·python·django