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

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. JS常用自定义函数总结

    JS常用自定义函数总结   1.原生JavaScript实现字符串长度截取 2.原生JavaScript获取域名主机 3.原生JavaScript清除空格 4.原生JavaScript替换全部 5.原 ...

  2. python之multiprocessing多进程

    multiprocessing 充分利用cpu多核一般情况下cpu密集使用进程池,IO密集使用线程池.python下想要充分利用多核CPU,就用多进程. Process 类Process 类用来描述一 ...

  3. 51单片机通过ESP8266模块与手机进行通讯(单片机)

    相关连接和资料下载: 个人博客 资料下载 Step1:配置ESP8266 通过USB转TTL模块把ESP8266模块和电脑连接起来,如图: 把ESP8266模块的VCC,GND,CH_PD,UTXD, ...

  4. 会了docker你又多了一个谈资(上)

    相信有到现在为止还是有很多同学只是听说过docker,但还不了解docker.也很想学习,但是又不知道从何入手,工作中又接触不到,而自己又懒得去翻阅各种学习资料,那么,读完本文,我保证,docker的 ...

  5. Linux VPS 常用重启命令

    重启vps:reboot CentOS重启ssh:/etc/init.d/sshd restart Debian/Ubuntu重启ssh:/etc/init.d/ssh restart 重启Lnmp: ...

  6. 使用jvisualvm远程监控tomcat(阿里云ECS)

    写在前面:  使用jvisualvm远程监控tomcat(阿里云ECS),连接是报错:service:jmx:rmi:////jndi/rmi:IP:端口//  连接到 IP:端口,网上找了很多资料, ...

  7. python 继承:重写、拓展(六)

    1.继承:父类有的子类也有 2.多继承:若继承多个父类有相同的函数,则继承前面的函数,传递参数的个数也与继承的函数位置有关 3.超继承:针对继承一个父类使用,不仅有父类的特写同时也有自己的新特性  s ...

  8. 红帽Linux故障定位技术详解与实例(2)

    红帽Linux故障定位技术详解与实例(2) 2011-09-28 14:26 圈儿 BEAREYES.COM 我要评论(0) 字号:T | T 在线故障定位就是在故障发生时, 故障所处的操作系统环境仍 ...

  9. CART 分类与回归树

    from www.jianshu.com/p/b90a9ce05b28 本文结构: CART算法有两步 回归树的生成 分类树的生成 剪枝 CART - Classification and Regre ...

  10. DevOps之Pipeline集成junit、jacoco、SonarQube(二)

    一.准备工作 1.准备一个持续集成的代码工程 工程下载地址: Github地址为:https://github.com/zbbkeepgoing/springboot-demo 2.springboo ...