设为首页 收藏本站
查看: 1449|回复: 0

[经验分享] golang中的reflect包用法

[复制链接]

尚未签到

发表于 2018-9-19 14:11:33 | 显示全部楼层 |阅读模式
  最近在写一个自动生成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
  

  未完待续。。。



运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-594353-1-1.html 上篇帖子: Golang 入门系列(一)Go环境搭建 下篇帖子: Golang json用法详解(一)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表