golang 使用reflect反射结构体
"反射结构体"是指在程序执行时,遍历结构体中的字段以及方法。
1.反射结构体
下面使用一个简单的例子说明如何反射结构体。
定义一个结构体,包括3个字段,以及一个方法。
通过reflect包,首先查看这个结构体对应的动态类型reflect.Type和动态值reflect.Value,并查看这个结构体对应的基本类型。
接着查看结构体的字段数量,并遍历每个字段。
打印每个字段的类型、值、以及tag标签。
最后,调用结构体中的方法,并打印返回结果。
具体代码如下。
package main
import (
"fmt"
"reflect"
)
type Orange struct {
size int `kitty:"size"`
Weight int `kitty:"wgh"`
From string `kitty:"source"`
}
func (this Orange) GetWeight() int {
return this.Weight
}
func main(){
orange := Orange{1, 18, "Shanghai"}
refValue := reflect.ValueOf(orange) // value
refType := reflect.TypeOf(orange) // type
fmt.Println("orange refValue:", refValue)
fmt.Println("orange refType:", refType)
orangeKind := refValue.Kind() // basic type
fmt.Println("orange Kind:", orangeKind)
fieldCount := refValue.NumField() // field count
fmt.Println("fieldCount:", fieldCount)
for i:=0; i < fieldCount; i++{
fieldType := refType.Field(i) // field type
fieldValue := refValue.Field(i) // field vlaue
fieldTag := fieldType.Tag.Get("kitty") // field tag
fmt.Println("fieldTag:", fieldTag)
fmt.Println("field type:", fieldType.Type)
fmt.Println("fieldValue:", fieldValue)
}
// method
result := refValue.Method(0).Call(nil)
fmt.Println("method result:", result[0])
}
输出结果:
orange refValue: {1 18 Shanghai}
orange refType: main.Orange
orange Kind: struct
fieldCount: 3
fieldTag: size
field type: int
fieldValue: 1
fieldTag: wgh
field type: int
fieldValue: 18
fieldTag: source
field type: string
fieldValue: Shanghai
method result: 18
另外, 如果反射时,使用的参数是结构体指针:
refValue := reflect.ValueOf(&orange) // value
则需要首先解引用指针,取得指针指向的对象:
refValue = refValue.Elem()
2.相关函数说明
2.1 Value.Kind()
func (v Value) Kind() Kind
其返回值为Kind,表示golang语言自身定义的基本类型:
type Kind uint
取值包括:
const (
Invalid Kind = iota
Bool
Int
Int8
Int16
Int32
Int64
Uint
Uint8
Uint16
Uint32
Uint64
Uintptr
Float32
Float64
Complex64
Complex128
Array
Chan
Func
Interface
Map
Ptr
Slice
String
Struct
UnsafePointer
)
2.2 Value.Elem()
func (v Value) Elem() Value
方法返回v指向的对象。
要求v必须是interface或指针。
2.3 Type.Elem()
type Type Interface{
// Elem returns a type's element type.
// It panics if the type's Kind is not Array, Chan, Map, Ptr, or Slice.
Elem() Type
... ...
}
返回指向对象的具体类型。
要求调用者必须是Array, Chan, Map, Ptr, or Slice。
例如,
i := 1
v := reflect.ValueOf(&i)
valueType := v.Type()
elemType := valueType.Elem()
fmt.Println("valueType:", valueType) //*int
fmt.Println("elemType:", elemType) // int
v是*int,则element type就是int。
例如,
sli := []string{"abc", "ef", "gh", "123"}
v := reflect.ValueOf(sli)
valueType := v.Type()
elemType := valueType.Elem()
fmt.Println("valueType:", valueType) // []string
fmt.Println("elemType:", elemType) // string
v是字符串数组,则element type就是字符串。
golang 使用reflect反射结构体的更多相关文章
- golang 兼容不同json结构体解析实践
线上服务器,同一个web接口有时需要兼容不同版本的结构体.这种情况思路是使用interface{}接收任意类型数据,结合reflect包处理. 如下,http接口调用者会传入不同的json结构数据(单 ...
- golang 通过reflect反射修改值
不是所有的反射值都可以修改.对于一个反射值是否可以修改,可以通过CanSet()进行检查. 要修改值,必须满足: 可以寻址 可寻址的类型: 指针指向的具体元素 slice的元素 可寻址的结构体的字段( ...
- 换个语言学一下 Golang (9)——结构体和接口
基本上到这里的时候,就是上了一个台阶了.Go的精华特点即将展开. 结构体定义 上面我们说过Go的指针和C的不同,结构体也是一样的.Go是一门删繁就简的语言,一切令人困惑的特性都必须去掉. 简单来讲,G ...
- golang:reflect反射
因为之前一直以C++为主要开发语言,所以刚接触go语言中的reflect时感觉很懵逼,因此决定找资料彻底学习一下. 到底反射是什么? https://blog.golang.org/laws-of-r ...
- golang基础--reflect反射
反射的知识点比较晦涩,后期会对此知识点展开深入的分析及示例代码展示 反射可达大提高程序的灵活性,使得inferface{}有更大的发挥余地 反射使用TypeOf和ValueOf函数从接口中获取目标对象 ...
- Golang 通过创建临时结构体实现 struct 内 interface struct 的 json 反序列化
原文链接 背景 type AData struct { A string `json:"a"` } type BData struct { B string `json:" ...
- C# 反射结构体struct的一个坑
今天代码用到了反射赋值,代码是这样写的: var objtype = obj.GetType(); var Fieldinfo = objtype.GetField("I64"); ...
- golang 修改数组中结构体对象的值的坑
对对象数组逐个修改元素属性时候没有成功,代码如下: for _, configure := range configures { configure.Price = specPriceMap[conf ...
- golang中的反射reflect详解
先重复一遍反射三定律: 1.反射可以将"接口类型变量"转换为"反射类型对象". 2.反射可以将"反射类型对象"转换为"接口类型变量 ...
随机推荐
- 解决postgresql数据库localhost可以连接,ip连接不了的问题
解决:windows环境下,postgresql数据库,localhost可以连接,ip地址连接不了. 解决办法: 1.打开postgresql安装目录下的配置文件 pg_hba.conf ...
- 25、Nginx常见典型故障
1.为什么nginx里面有的是浏览器渲染出的页面,有的时候就变成下载文件? 这个一个取决于服务端nginx,一个取决于你浏览器.在Nginx服务端的配置文件目录下,有一个mime.types 文件,内 ...
- Linux部署java和tomcat的运行环境
Linux部署java和tomcat的运行环境 1.上传下载的jdk的rpm包和tomcat的tar包,我是放到/opt目录了,文件直接去官网下载即可. 2.如果之前安装过其他版本的jdk,最好先现在 ...
- 标准C语言(5)
无法预知的数字叫随机数,rand标准函数可以用来获得随机数,为了使用这个标准函数需要包含stdlib.h头文件 srand标准函数用来设置随机数种子,这个函数把一个整数作为种子使用不同的种子可以得到不 ...
- 《编译原理》构造与正规式 (0|1)*01 等价的 DFA - 例题解析
<编译原理>构造与正规式 (0|1)*01 等价的 DFA - 例题解析 解题步骤: NFA 状态转换图 子集法 DFA 的状态转换矩阵 DFA 的状态转图 解: 已给正规式:(0|1)* ...
- 2019.12.9java公文流转系统
自己来写这个系统真是没有什么思路.就弄了个登陆界面,在数据库建了个表,其它的代码一直有错误,登陆不进去.
- Java介绍、环境的搭建及结构化程序
一.Java 简介及环境配置: JDK和JRE的区别:JRE(Java Runtime Environment)Java运行时环境有些程序运行需要Java环境,因此JRE只是给客户端使用的. JDK( ...
- nmap脚本(nse)使用总结
nmap脚本主要分为以下几类,在扫描时可根据需要设置--script=类别这种方式进行比较笼统的扫描: auth: 负责处理鉴权证书(绕开鉴权)的脚本 broadcast: 在局域网内探查更多服务 ...
- Linux 内核源代码的几个C语言技巧
1.#define中使用do{statement}while(0)保证statement无论在何处都能正确执行一次2.将链表操作抽象出来,与宿主结果相互独立.所有的链表操作都作用与list_head, ...
- node + mongoDB
在MongoDB安装这篇博客中已经创建了一个bella_blog的数据库,该数据已经包含了user集合. 下面就可以在node sever端用MongoDB了. Mongoose库简而言之就是在nod ...