本文首发于公众号:Hunter后端

原文链接:Golang基础笔记十六之反射

反射可以用于程序在运行时检查、修改自身类型和值,主要通过 reflect 包实现。

首先,我们提出一个需求,要打印出一个结构体 struct 的各个字段及其对应的标签数据,按照当前的笔记内容是无法解决该问题的,但是我们可以使用反射操作来完成。

以下是本篇笔记目录:

  1. 变量的类型和值
  2. 修改变量的值
  3. 遍历结构体字段
  4. 动态调用函数

1、变量的类型和值

先引入 reflect 模块:

import (
"reflect"
)

我们可以通过 reflect.TypeOf() 获取变量的类型:

var x float64 = 3.5

t := reflect.TypeOf(x)

返回的 t 是 Type 接口,我们可以进一步调用 t 的方法来获取类型信息:

// 变量的类型名称:
fmt.Println("x 的类型名称是: ", t.Name()) // 判断类型的类别:
fmt.Println("x 的类型是否是 float64: ", t.Kind() == reflect.Float64)

获取变量的值信息:

v := reflect.ValueOf(x)
fmt.Println("value: ", v.Float() == 3.5)

2、修改变量的值

如果要修改这个变量的值,我们需要用到指针,以下是操作示例:

var x float64 = 3.5

// 这里获取的是变量的地址的值,如果直接 reflect.ValueOf(x) 获取的是 x 的副本
p := reflect.ValueOf(&x) // Elem() 方法获取指针指向的实际值,是解引用的操作
v := p.Elem() // 重新赋值的操作
v.SetFloat(4.9)
fmt.Println("new value: ", x)

3、遍历结构体字段

我们先定义一个结构体如下:

type Person struct {
Id int `json:"id" form:"id"`
Name string `json:"name"`
}

打印一个 Person 示例各个字段的名称及其值的操作如下:

p := Person{
Id: 1,
Name: "hunter",
}
t := reflect.TypeOf(p)
v := reflect.ValueOf(p) for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
value := v.Field(i) fmt.Printf("field_name:%s, field_type:%s, value:%v\n", field.Name, field.Type, value.Interface())
}

在这里,我们通过 t.NumField() 方法获取到 p 的字段个数,并使用 t.Field(i)v.Field(i) 获取到对应字段类型和值。

接着对于每个 field 和 value,我们可以打印出对应的字段名称,字段类型和值。

我们还可以使用 field.Tag.Get() 的方式获取到字段标签的值:

fmt.Printf("json_tag:%s, form_tag:%s\n", field.Tag.Get("json"), field.Tag.Get("form"))

如果后续我们介绍 Golang 的 validator 模块,可以了解到,validator 就是通过 struct 定义的标签使用反射来对字段值进行验证的。

4、动态调用函数

我们还可以使用反射来动态调用函数,比如某个函数如下:

func Add(a, b int) int {
return a + b
}

使用反射动态调用的操作如下:

func main() {
targetFunc := reflect.ValueOf(Add) args := []reflect.Value{reflect.ValueOf(2), reflect.ValueOf(5)} result := targetFunc.Call(args)
fmt.Println("动态调用 Add 函数,result: ", result[0].Int())
}

注意:虽然反射可以为我们提供一些便利的操作,但是代码的可读性和可维护性会降低,且会降低性能,需要在实际生产中谨慎使用。

Golang基础笔记十六之反射的更多相关文章

  1. Bootstrap <基础二十六>进度条

    Bootstrap 进度条.在本教程中,你将看到如何使用 Bootstrap 创建加载.重定向或动作状态的进度条. Bootstrap 进度条使用 CSS3 过渡和动画来获得该效果.Internet ...

  2. python3.4学习笔记(十六) windows下面安装easy_install和pip教程

    python3.4学习笔记(十六) windows下面安装easy_install和pip教程 easy_install和pip都是用来下载安装Python一个公共资源库PyPI的相关资源包的 首先安 ...

  3. Django笔记十六之aggregate聚合操作

    本文首发于微信公众号:Hunter后端 原文链接:Django笔记十六之aggregate聚合操作 这一篇笔记介绍一下关于聚合的操作,aggregate. 常用的聚合操作比如有平均数,总数,最大值,最 ...

  4. css3基础教程十六变形与动画animation

    前面我们讲过的变形与动画一般都是通过鼠标的单击.获得焦点,被点击或对元素进行一定改变后以后触发效果的,那么有没有像Flash一样自动播放的动画效果呢?答案当然是肯定的,这就是我们今天要讲到的anima ...

  5. linux基础-第十六单元 yum管理RPM包

    第十六单元 yum管理RPM包 yum的功能 本地yum配置 光盘挂载和镜像挂载 本地yum配置 网络yum配置 网络yum配置 Yum命令的使用 使用yum安装软件 使用yum删除软件 安装组件 删 ...

  6. MYSQL基础笔记(六)- 数据类型一

    数据类型(列类型) 所谓数据烈性,就是对数据进行统一的分类.从系统角度出发时为了能够使用统一的方式进行管理,更好的利用有限的空间. SQL中讲数据类型分成三大类:1.数值类型,2.字符串类型和时间日期 ...

  7. (C/C++学习笔记) 十六. 预处理

    十六. 预处理 ● 关键字typeof 作用: 为一个已有的数据类型起一个或多个别名(alias), 从而增加了代码的可读性. typedef known_type_name new_type_nam ...

  8. Java基础学习笔记十六 集合框架(二)

    List List接口的特点: 它是一个元素存取有序的集合.例如,存元素的顺序是11.22.33.那么集合中,元素的存储就是按照11.22.33的顺序完成的. 它是一个带有索引的集合,通过索引就可以精 ...

  9. 文件的上传Commons FileUpload(web基础学习笔记十六)

    一.表单设置 <form action="<%=request.getContextPath()%>/jsp/admin/doAdd.jsp" enctype=& ...

  10. Golang基础(5):Go语言反射规则

    Go语言反射规则 - The Laws of Reflection 转:http://my.oschina.net/qbit/blog/213720 原文地址:http://blog.golang.o ...

随机推荐

  1. ZeRO:一种去除冗余的数据并行方案

    ZeRO:一种去除冗余的数据并行方案 目前训练超大规模语言模型主要有两条技术路线: TPU + XLA + TensorFlow/JAX GPU + Pytorch + Megatron + Deep ...

  2. pandas.read_csv() 报错 OSError: Initializing from file failed

    pandas.read_csv() 报错 OSError: Initializing from file failed,一般由两种情况引起:一种是函数参数为路径而非文件名称,另一种是函数参数带有中文. ...

  3. 【译】Visual Studio 2022 v17.14 现已正式发布!

    我们很高兴地宣布 Visual Studio 2022 17.14 正式发布!此版本延续了我们的使命--为开发者提供更快.更智能且更高效的工具,以应对各种开发工作. 在这个版本中有很多开发者喜欢的东西 ...

  4. vue3和ts和vue-cropper 实现图片裁剪预览

    ​​Vue-Cropper​​ 是一个基于 Vue.js 的图片裁剪组件库,专为 Web 应用设计.当你在网上搜索的时候发现还有一个叫cropper的库,下面是他们的区别: 二.快速上手 //npm ...

  5. String Game

    二分答案的练手题,虽然很淼,但本题解提供一种清爽的解. 首先,二分什么: 当然是二分可以删除的次数,并使用 check 函数判断该值是否合法.这点毋庸置疑. check 怎么写. 首先,我们假设可以删 ...

  6. 构建RPM之SPEC详解

    一.简单说明 在centos/rhel的系统使用中,我们会涉及自己构建一些rpm包在centos/rhel的系统中进行安装,这里涉及rpm打包环境的部署.SPEC文件的编写相关,下面我们具体进行说明. ...

  7. 【前端AI实践】简说AI大模型:什么时代了你还不会这些AI大模型的基本概念和使用吗

    如果你是前端开发者,可能已经用过像 ChatGPT.GitHub Copilot 这样的 AI 工具.它们背后都有一个核心能力在支撑:AI 大模型. 那这个"大模型"到底是个啥?它 ...

  8. wc记录

    WC记录 咋可 随机化 CF1746F 给每个值随机成\(0/1\),然后查询区间内的所有数的和是否\(\equiv0\mod k\) 考虑错误率,对于一个不合法的权值,设其有\(r\)个,考虑区间内 ...

  9. centos7搭建postgresql-14

    环境:centos7  + pg 14 1:在postgresql官网下载页面,根据提示下载 https://www.postgresql.org/download/linux/redhat/ 2 连 ...

  10. ET框架服务端部署到Linux--升级3.1

    框架升级3.1参考:https://www.cnblogs.com/cj8988/p/14098017.html 安装.netcore 3.1 我的安装方法,直接下载文件(Centos7系统,之前安装 ...