golang中的reflect包用法
最近在写一个自动生成api文档的功能,用到了reflect包来给结构体赋值,给空数组新增一个元素,这样只要定义一个input结构体和一个output的结构体,并填写一些相关tag信息,就能使用程序来生成输入和输出的相关文档。
介绍
reflect包是golang中很重要的一个包,实现了在运行时允许程序操纵任意类型对象的功能。可以看下文档简单了解一下。
在reflect中,最重要的是Value类,只有先获取到一个对象或者变量的Value对象后,我们才可以对这个对象或者变量进行更进一步的分析和处理。我们可以使用reflect.ValueOf()方法获取Value对象。
var i int
value := reflect.ValueOf(i) // 使用ValueOf()获取到变量的Value对象
type S struct {
a string
}
var s S
value2 := reflect.ValueOf(s) // 使用ValueOf()获取到结构体的Value对象
获取到对象或者变量的Value对象后,我们就可以对他们进一步的操作了。
1.获取对象或者变量的类型(Value.Type()和Value.Kind())
Value.Type()和Value.Kind()这两个方法都可以获取对象或者变量的类型,如果是变量的话,使用这两个方法获取到的类型都是一样,差别是结构体对象,举个例子看一下:
var i int
value := reflect.ValueOf(i)
log.Println(value.Type()) //输出:int
log.Println(value.Kind()) //输出:int
type S struct {
a string
}
var s S
value2 := reflect.ValueOf(s) // 使用ValueOf()获取到结构体的Value对象
log.Println(value2.Type()) //输出:S
log.Println(value2.Kind()) //输出:struct
变量i使用kind和type两个方法都输出了int,而结构体s的Type()方法输出了S,Kind()方法输出了struct,由此可以总结如下,如果你想拿到结构体里面定义的变量信息的时候,使用Type(f)方法。如果只是相判断是否是结构体时,就使用Kind()
2.获取变量的值和给变量赋值
获取变量的值使用value.Interface()方法,该方法会返回一个value的值,不过类型是interface。给变量赋值需要先判断该变量的类型,使用之前提到过的Value.Kind()方法,如果变量的类型是reflect.Int,我们就可以使用Value.SetInt()方法给变量赋值。下面是一个例子:
var i int = 1
// 获取Value,这里注意,如果你要改变这个变量的话,需要传递变量的地址
value := reflect.ValueOf(&i)
// value是一个指针,这里获取了该指针指向的值,相当于value.Elem()
value = reflect.Indirect(value)
// Interface是获取该value的值,返回的是一个interface对象
log.Println(value.Interface()) // 输出:1
// 把变量i的值设为2
if value.Kind() == reflect.Int {
value.SetInt(2)
}
log.Println(value.Interface()) // 输出:2
给结构体对象中的成员变量赋值的方法:
type S struct {
A string // 注意:只有大写开头的成员变量可以Set
}
s := S{"x"}
value := reflect.ValueOf(&s)
value = reflect.Indirect(value)
//value是结构体s,所以打印出来的是整个结构体的信息
log.Println(value.Interface()) //输出: {x}
f0 := value.FieldByName("A") //获取结构体s中第一个元素a
log.Println(f0) // 输出: x
if f0.Kind() == reflect.String {
if f0.CanSet() {
f0.SetString("y")
}
}
log.Println(f0) // 输出: y
log.Println(value.Interface()) //输出: {y}
结构体这里需要注意的是,只有公有的成员变量可以被reflect改变值,私有的变量是无法改变值得。
3.获取结构体成员变量的tag信息
由于golang变量大小写和公有私有息息相关,所以码农门很难按照自己的意愿来定义变量名。于是golang提供了tag机制,来给变量提供一个标签,这个标签可以作为一个别名,来给一些存储结构来获取结构体变量名字使用。下面是一个获取结构体成员变量tag信息的例子:
type S struct {
A string `json:"tag_a"`
}
s := S{}
value := reflect.ValueOf(&s)
value = reflect.Indirect(value)
//获取结构体s的类型S
vt := value.Type()
//获取S中的A成员变量
f, _ := vt.FieldByName("A")
//获取成员变量A的db标签
log.Println(f.Tag.Get("json")) //输出: tag_a
未完待续。。。
golang中的reflect包用法的更多相关文章
- golang中的rpc包用法
RPC,即 Remote Procedure Call(远程过程调用),说得通俗一点就是:调用远程计算机上的服务,就像调用本地服务一样. 我所在公司的项目是采用基于Restful的微服务架构,随着微服 ...
- golang中os/exec包用法
exec包执行外部命令,它将os.StartProcess进行包装使得它更容易映射到stdin和stdout,并且利用pipe连接i/o. 1.func LookPath(file string) ( ...
- golang格式化输出-fmt包用法详解
golang格式化输出-fmt包用法详解 注意:我在这里给出golang查询关于包的使用的地址:https://godoc.org 声明: 此片文章并非原创,大多数内容都是来自:https:// ...
- Golang中的RegExp正则表达式用法指南
------------------------------------------------------------ Golang中的正则表达式 ------------------------- ...
- golang中的context包
标准库的context包 从设计角度上来讲, golang的context包提供了一种父routine对子routine的管理功能. 我的这种理解虽然和网上各种文章中讲的不太一样, 但我认为基本上还是 ...
- golang中container/list包源码分析
golang源码包中container/list实际上是一个双向链表 提供链表的一些基本操作,下面就结合定义和接口进行下说明 1. 定义 // Element is an element of a l ...
- golang中container/heap包源码分析
学习golang难免需要分析源码包中一些实现,下面就来说说container/heap包的源码 heap的实现使用到了小根堆,下面先对堆做个简单说明 1. 堆概念 堆是一种经过排序的完全二叉树,其中任 ...
- golang中net/http包的简单使用
一.介绍 http包提供了http客户端和服务端的实现 Get,Head,Post和PostForm函数发出http.https的请求 程序在使用完回复后必须关闭回复的主体 #简单的访问网站,由于没有 ...
- golang中 "下划线" 的用法
1.忽略返回值 这个应该是最简单的用途,比如某个函数返回三个参数,但是我们只需要其中的两个,另外一个参数可以忽略,这样的话代码可以这样写: v1, v2, _ := function(...) 2.用 ...
随机推荐
- zoom:1-hasLayout
在现代浏览器,如果子元素float,则父元素不会自动被撑开 #nofloatbox { border: 1px solid #FF0000; background: #CCC; width:200px ...
- 定制自己的Unity脚本模板
有时候想给脚本添加符合自己编程习惯的内容,或是一些个性化信息.而作为一个多多少少有点强迫症的人,这种东西要加就得每个脚本都加上,不然看着多不爽! 于是就得每添加一个脚本就去修改一下,很麻烦. 但是,在 ...
- 解析STL中典型的内存分配
1 vector 在C++中使用vector应该是非常频繁的,但是你是否知道vector在计算内存分配是如何么? 在c++中vector是非常类似数组,但是他比数组更加灵活,这就表现在他的大小是可以自 ...
- WPF ResourceDictionary的使用
作用:一个应用程序中,某个窗口需要使用样式,但是样式非常多,写在一个窗口中代码分类不方便.最好Style写在专门的xaml文件中,然后引用到窗口中,就像HTML引用外部css文件一样. 初衷:就在于可 ...
- 在ASP.NET MVC中使用JQ插件datatable
1. Models public class Citys { public int Id { get; set; } public string CityName { get; set; } publ ...
- Select与Epoll比较
一.问题引出 联系区别 问题的引出,当需要读两个以上的I/O的时候,如果使用阻塞式的I/O,那么可能长时间的阻塞在一个描述符上面,另外的描述符虽然有数据但是不能读出来,这样实时性不能满足要求,大概的解 ...
- 车大棒浅谈for循环+canvas实现黑客帝国矩形阵
背景: 一日在网上闲逛的之时,突然看到一个利用JQ插件实现canvas实现的电影黑客帝国的小Demo.觉得创意不错,就下载下来研究一下. 网上浏览jQuery的写法 $(document).ready ...
- Grunt + Bower—前端构建利器
目前比较流行的WEB开发的趋势是前后端分离.前端采用重量级的Javascript框架,比如Angular,Ember等,后端采用restful API的Web Service服务,通过JSON格式进行 ...
- “权限系统_基于HUI”的简单介绍和交流
昂,最近比较闲,写了个权限系统. 后端框架还是老样子,基于本人自己搭建的后台基础开发框架"Spring_Mvc_EF":前端框架,我挑选了一阵子,最后选用了HUI前端开发框架,因为 ...
- 如何用webbrowser获取ajax动态生成的网页的源码?
1.步骤一:修改IE内核的版本(这个方法厉害了) public Form1() { InitializeComponent();int BrowserVer, RegVal; // get the i ...