"反射结构体"是指在程序执行时,遍历结构体中的字段以及方法。

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反射结构体的更多相关文章

  1. golang 兼容不同json结构体解析实践

    线上服务器,同一个web接口有时需要兼容不同版本的结构体.这种情况思路是使用interface{}接收任意类型数据,结合reflect包处理. 如下,http接口调用者会传入不同的json结构数据(单 ...

  2. golang 通过reflect反射修改值

    不是所有的反射值都可以修改.对于一个反射值是否可以修改,可以通过CanSet()进行检查. 要修改值,必须满足: 可以寻址 可寻址的类型: 指针指向的具体元素 slice的元素 可寻址的结构体的字段( ...

  3. 换个语言学一下 Golang (9)——结构体和接口

    基本上到这里的时候,就是上了一个台阶了.Go的精华特点即将展开. 结构体定义 上面我们说过Go的指针和C的不同,结构体也是一样的.Go是一门删繁就简的语言,一切令人困惑的特性都必须去掉. 简单来讲,G ...

  4. golang:reflect反射

    因为之前一直以C++为主要开发语言,所以刚接触go语言中的reflect时感觉很懵逼,因此决定找资料彻底学习一下. 到底反射是什么? https://blog.golang.org/laws-of-r ...

  5. golang基础--reflect反射

    反射的知识点比较晦涩,后期会对此知识点展开深入的分析及示例代码展示 反射可达大提高程序的灵活性,使得inferface{}有更大的发挥余地 反射使用TypeOf和ValueOf函数从接口中获取目标对象 ...

  6. Golang 通过创建临时结构体实现 struct 内 interface struct 的 json 反序列化

    原文链接 背景 type AData struct { A string `json:"a"` } type BData struct { B string `json:" ...

  7. C# 反射结构体struct的一个坑

    今天代码用到了反射赋值,代码是这样写的: var objtype = obj.GetType(); var Fieldinfo = objtype.GetField("I64"); ...

  8. golang 修改数组中结构体对象的值的坑

    对对象数组逐个修改元素属性时候没有成功,代码如下: for _, configure := range configures { configure.Price = specPriceMap[conf ...

  9. golang中的反射reflect详解

    先重复一遍反射三定律: 1.反射可以将"接口类型变量"转换为"反射类型对象". 2.反射可以将"反射类型对象"转换为"接口类型变量 ...

随机推荐

  1. Linux工具之netstat

        1.简介   Netstat 命令用于显示各种网络相关信息,如网络连接,路由表,接口状态 (Interface Statistics),masquerade 连接,多播成员 (Multicas ...

  2. Spring Boot热部署插件

    在实际开发中,我们修改某些代码逻辑功能或页面都需要重启应用,这无形中降低了开发效率,热部署是指当我们修改代码后,服务能自动重启加载新修改的内容,而不需要重启应用,这样大大提高了我们开发的效率. Spr ...

  3. java8学习之Stream分组与分区详解

    Stream应用: 继续举例来操练Stream,对于下面这两个集合: 需求是:将这两个集合组合起来,形成对各自人员打招呼的结果,输出的结果如: "Hi zhangsan".&quo ...

  4. 背包 || NOIP 2018 D1 T2 || Luogu P5020 货币系统

    题面:P5020 货币系统 题解: 显然要求的货币系统是当前货币系统的子集时答案会更优,于是考虑从当前货币系统中删数 一个大数如果能被其他小数表示出来,它就可以去掉 把数据排个序去个重,然后直接背包 ...

  5. windows2012下一端口多网站 Apache配置

    援引自https://www.cnblogs.com/huangtailang/p/6026828.html 1.在httpd.conf文件里启用虚拟主机功能,即去掉下面配置项前面的# #LoadMo ...

  6. qt5--树形控件QTreeWidget

    需要       #include <QTreeWidget>               #include <QTreeWidgetItem> #include " ...

  7. [Linux系统] (2)用户权限管理

    示例---普通用户之间的文件共享:假设公司有2个项目组,共享同一台服务器. 1.为两个项目组各创建一个用户: useradd leo01 useradd leo02 2.为两个新用户设置密码: pas ...

  8. 大视频上传T级别解决方案

    核心原理: 该项目核心就是文件分块上传.前后端要高度配合,需要双方约定好一些数据,才能完成大文件分块,我们在项目中要重点解决的以下问题. * 如何分片: * 如何合成一个文件: * 中断了从哪个分片开 ...

  9. Miller Rabin 算法简介

    0.1 一些闲话 最近一次更新是在2019年11月12日.之前的文章有很多问题:当我把我的代码交到LOJ上,发现只有60多分.我调了一个晚上,尝试用{2, 3, 5, 7, 11, 13, 17, 1 ...

  10. ZOJ3649 Social Net

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3649 这题倍增维护信息之多,也能算是一道毒瘤题了-- 解题思路 ...