Golang reflect反射的使用实例
作者:常鱼 发布时间:2024-05-05 09:32:17
标签:Golang,reflect,反射
首先有一段以下结构体的定义
type User struct {
UserName string
UserId int `name:"uid"`
}
初始化一个结构体的实例
u := User{"octoboy", 101}
获取字段名
首先获取变量的Type变量
t := reflect.TypeOf(u)
需要注意的是,如果传入的u是个指针,比如&User{"octoboy", 101}
if t.Kind() == reflect.Ptr {
t = t.Elem()
}
这里通过Kind()函数获取变量的类型,判断如果类型为指针 需要使用Elem()获取指针指向的内容。
然后遍历结构体的字段,获取其字段名称
for i := 0; i < t.NumField(); i++ {
fmt.Println(t.Field(i).Name)
}
输出结果:
UserName
UserId
获取字段类型和值
v := reflect.ValueOf(u)
if v.Kind() == reflect.Ptr { //类型为指针 需要取elem
v = v.Elem()
}
获取字段的值或者赋值,需要用到ValueOf方法
for i := 0; i < v.NumField(); i++ {
//v.Field(i).Int() v.Field(i).String() 都可以把值返回出来,相当于断言 类型不匹配会直接panic
//直接断成interface 任意类型
fmt.Println(v.Field(i).Interface())
}
输出结果:
zyg
101
继续输出成员变量的类型
for i := 0; i < v.NumField(); i++ {
fmt.Println(v.Field(i).Kind())
}
输出结果:
string
int
设置字段值
静态赋值
//设置字段值
va := reflect.ValueOf(&u) //这里必须使用指针 否则后面调用Set无法使用无地址的值
if va.Kind() == reflect.Ptr { //类型为指针 需要取elem 意为取它指向的内容值
va = va.Elem()
for i := 0; i < va.NumField(); i++ {
//两种方法取设置字段的值,第二种更为统一
if va.Field(i).Kind() == reflect.String {
//重要 如果需要使用set取修改u中的值,需要在ValueOf中传入u的地址。否则会因为SetString使用了一个不能被寻址的值而造成panic
va.Field(i).SetString("octoboy")
}
if va.Field(i).Kind() == reflect.Int {
va.Field(i).Set(reflect.ValueOf(123))
}
}
interface切片映射成结构体(动态赋值)
//练手
values := []interface{}{"octoboy", 123}
for i := 0; i < va.NumField(); i++ {
if reflect.ValueOf(values[i]).Kind() == va.Field(i).Kind() {
va.Field(i).Set(reflect.ValueOf(values[i]))
}
}
打印以上两种结构题变量
输出结果:
&{octoboy 123}
进阶—map映射成结构体
有如下代码
//练习 把map映射成struct
set := map[string]interface{}{
"UserName": "zyg",
"UserId": 101,
"Age": 19,
"Sex": 1,
}
user := &User{}
MapToStruct(set, user)
fmt.Println(user)
要求将map映射到user结构题中,即如果User的字段名如存在于map的key中,则将对应的value值赋给user结构题的成员变量
有如下实现
//str类型为interface{} 代表可以传入任意的结构体
func MapToStruct(m map[string]interface{}, str interface{}) {
val := reflect.ValueOf(str)
if val.Kind() != reflect.Ptr {//必须是指针 否则无法用Set赋值
panic(any("must be ptr!"))
}
val = val.Elem()
if val.Kind() != reflect.Struct { //指针指向的必须是结构体
panic(any("must be struct"))
}
for i := 0; i < val.NumField(); i++ {
name := val.Type().Field(i).Name //value转type后取字段名称
if v, ok := m[name]; ok { //如果根据tag做映射,就使用val.Type().Field(i).Tag.Get("name")作为key
if reflect.ValueOf(v).Kind() == val.Field(i).Kind() {
val.Field(i).Set(reflect.ValueOf(v))
}
}
}
}
来源:https://blog.csdn.net/kingu_crimson/article/details/127665684


猜你喜欢
- 安装先下载源码,地址:ps://pypi.python.org/pypi/IPy/">https://pypi.python
- 最近在用python连接sqlserver读取数据库,读取数据时候在本机电脑正常,但是把程序部署到服务器运行时一直报错“未发现数据源名称并且
- 1、项目背景对于不会PS的小伙伴,抠图是一个难度系数想当高的活儿,某宝照片抠图和证件照换底色均价都是5元RMB,所以今天要介绍的这款神工具,
- 在写脚本的过程中,除了发送form表单参数之外,我们还会发送json格式的参数。那么碰见json格式要怎么发送呢,这篇我们来解决这个问题。直
- 可能许多同学对SQL Server的备份和还原有一些了解,也可能经常使用备份和还原功能,我相信除DBA之外我们大部分开发员队伍对备份和还原只
- 本文实例为大家分享了微信小程序实现图片上传功能的具体代码,供大家参考,具体内容如下前端:微信开发者工具后端:.Net服务器:阿里云这里介绍微
- MySQL是一个跨平台的开源关系型数据库管理系统,是我们常用的最经济实惠的数据库,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特
- 我就废话不多说了,直接上代码吧!#Python的matrix转置matrix = [[1,2,3,4],[5,6,7,8],[9,10,11
- 第一种# -*- coding: utf-8 -*-# @Time : 2020/3/16 21:26# @File : get_text_
- 1.加载数据库,数据库的配置不能写死在seting.py文件中,下面的方式是读取另外一个文件,配置数据库:config = '
- 本文例举了ASP实例关于ASP与ACCESS链接的两种方式。<%dim dd,connstrdd="data.mdb&quo
- 背景:使用python脚本传递参数在实际工作过程中还是比较常用,以下提供了好几种的实现方式:一、使用sys.argv的数组传入说明:使用sy
- 第一次使用python写程序,确实比C/C++之类方便许多。既然这个抽奖的数据不大,对效率要求并不高,所以采用python写,更加简洁、清晰
- 本文实例为大家分享了python定时提取实时日志的具体代码,供大家参考,具体内容如下这是一个定时读取 实时日志文件的程序。目标文件是targ
- 前言优雅关机就是服务端关机命令发出后不是立即关机,而是等待当前还在处理的请求全部处理完毕后再退出程序,是一种对客户端友好的关机方式。而执行C
- 本文实例讲述了python sqlite的Row对象操作。分享给大家供大家参考,具体如下:一 代码import sqlite3conn=sq
- 本文实例讲述了python实现从ftp服务器下载文件的方法。分享给大家供大家参考。具体实现方法如下:import ftplibftp = f
- Turtle库是Python语言中一个很流行的绘制图像的函数库,想象一个小乌龟,在一个横轴为x、纵轴为y的坐标系原点,(0,0)位置开始,它
- 获取所有variable(每个op中可训练的张量)的name:for variable_name in tf.global_variable
- 本文实例讲述了javascript实现表格增删改操作的方法。分享给大家供大家参考。具体实现方法如下:<!DOCTYPE html PU