Go 语言也有反射的机制,通过这种机制可以大大提高程序的灵活性。

reflect包中的 TypeOf 与 ValueOf 方法

首先,当我们想要使用反射技术的时候,我们需要先引用 reflect 包。

  1. import (
  2. "fmt"
  3. "reflect"
  4. )

之后,我们就可以通过reflect包中的TypeOf方法来取到类型,并且使用ValueOf方法来获取字段及方法。我们来看一个实例

  1. // reflect.go
  2. package main
  3.  
  4. import (
  5. "fmt"
  6. "reflect"
  7. )
  8.  
  9. type User struct {
  10. Name string
  11. Age int
  12. Sex string
  13. }
  14.  
  15. func (u User) SayHello() {
  16. fmt.Println("Hello there, I am %s ...", u.Name)
  17. }
  18.  
  19. func main() {
  20. user := User{
  21. "Tony",
  22. ,
  23. "male"}
  24. info(user)
  25. }
  26.  
  27. func info(o interface{}) {
  28. t := reflect.TypeOf(o)
  29. fmt.Printf("Type is: %s \n", t.Name())
  30.  
  31. fmt.Printf("Fields are: \n")
  32.  
  33. // find out fileds
  34. v := reflect.ValueOf(o)
  35.  
  36. for i := ; i < t.NumField(); i++ {
  37. f := t.Field(i)
  38. val := v.Field(i).Interface()
  39. fmt.Printf("%6s: %v=%v\n", f.Name, f.Type, val)
  40. }
  41.  
  42. // find out methods
  43. for i := ; i < t.NumMethod(); i++ {
  44. m := t.Method(i)
  45. fmt.Printf("%6s: %v\n", m.Name, m.Type)
  46. }
  47. }

output:

使用反射修改类型

如果我们需要通过反射的方式来修改类型的字段,那么传入给ValueOf()方法的参数应该是对象的引用。

  1. // reflect1.go
  2. package main
  3.  
  4. import (
  5. "fmt"
  6. "reflect"
  7. )
  8.  
  9. type People struct {
  10. Name string
  11. Age int
  12. }
  13.  
  14. func main() {
  15. p := People{"Tony", }
  16. fmt.Printf("my name is: %s\n", p.Name)
  17.  
  18. val := reflect.ValueOf(&p)
  19. f := val.Elem().FieldByName("Name")
  20. f.SetString("Tom")
  21.  
  22. fmt.Printf("my name is: %s\n", p.Name)
  23. }

使用反射来“动态”调用方法

  1. // reflect1.go
  2. package main
  3.  
  4. import (
  5. "fmt"
  6. "reflect"
  7. )
  8.  
  9. type People struct {
  10. Name string
  11. Age int
  12. }
  13.  
  14. func (p People) Hello(name string) {
  15. fmt.Printf("Hello there, I am %s", name)
  16. }
  17.  
  18. func main() {
  19. p := People{"Tony", }
  20. v := reflect.ValueOf(p)
  21. mv := v.MethodByName("Hello")
  22.  
  23. args := []reflect.Value{reflect.ValueOf("Tom")}
  24. mv.Call(args)
  25. }

需要注意的是,通过反射调用方法的时候需要以slice的形式传入参数,

  1. args := []reflect.Value{reflect.ValueOf("Tom")}
  2.  
  3.  最后使用method.call来调用方法
  4. mv.Call(args)

Go - reflection的更多相关文章

  1. Fresnel Reflection - 菲涅尔反射

    [Fresnel Reflection - 菲涅尔反射] “菲涅尔”是一个人的名字,因为他发现了一个有关反射的光学现象,这个现象就用这个人的名字命名了.那么,是什么现象呢? 这就是反射/折射与视点角度 ...

  2. CSharpGL(13)用GLSL实现点光源(point light)和平行光源(directional light)的漫反射(diffuse reflection)

    CSharpGL(13)用GLSL实现点光源(point light)和平行光源(directional light)的漫反射(diffuse reflection) 2016-08-13 由于CSh ...

  3. Scala Reflection - Mirrors,ClassTag,TypeTag and WeakTypeTag

    反射reflection是程序对自身的检查.验证甚至代码修改功能.反射可以通过它的Reify功能来实时自动构建生成静态的Scala实例如:类(class).方法(method).表达式(express ...

  4. [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦

    [.net 面向对象程序设计进阶] (21) 反射(Reflection)(下)设计模式中利用反射解耦 本节导读:上篇文章简单介绍了.NET面向对象中一个重要的技术反射的基本应用,它可以让我们动态的调 ...

  5. [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程

    [.net 面向对象程序设计进阶] (20) 反射(Reflection)(上)利用反射技术实现动态编程 本节导读:本节主要介绍什么是.NET反射特性,.NET反射能为我们做些什么,最后介绍几种常用的 ...

  6. Could not load type 'System.Reflection.AssemblySignatureKeyAttribute' from assembly 'mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c

    错误: Could not load type 'System.Reflection.AssemblySignatureKeyAttribute' from assembly 'mscorlib, V ...

  7. 代替Reflection(反射)的一些方法

    Reflection(反射)是深入学习.Net必须掌握的技能之一.最初学Reflection的时候,的确是被惊住了,原来还可以这样.只要给你一个Assembly, 你就能获取到其中所有的类型,根据类型 ...

  8. Leetcode: Line Reflection

    Given n points on a 2D plane, find if there is such a line parallel to y-axis that reflect the given ...

  9. 反射(Reflection)

    反射主要用于在程序运行期间动态解析相关类的类名,命名空间,属性,方法并进行相应操作,以下通过两个简单的例子进行了说明: 示例1:调用程序集内部方法,运行时动态获取相关类的信息,包括类名,命名空间等信息 ...

  10. 异常:“System.Reflection.Metadata”已拥有为“System.Collections.Immutable”定义的依赖项

    参考动态执行T4模板:https://msdn.microsoft.com/zh-cn/library/bb126579.aspx 我项目是.NET Framework 4.5控制台应用程序写的. 执 ...

随机推荐

  1. JQuery遍历CheckBox踩坑记

    $("#checkbox_id").attr("checked"); //获取一个CheckBox的状态(有没有被选中,返回true/false) $(&quo ...

  2. Machine Learning|Andrew Ng|Coursera 吴恩达机器学习笔记(完结)

    Week 1: Machine Learning: A computer program is said to learn from experience E with respect to some ...

  3. 关于Objective-C 2.0 的垃圾收集

      Objective-C 2.0最大的增强可能就是垃圾收集了(Garbage Collection).与“垃圾收集”对应的是传统的引用计数(Reference Count)内存管理形式. 使用了垃圾 ...

  4. js里获取html真实舞台宽高

    var winSize = {width:document.documentElement.clientWidth,height:document.documentElement.clientHeig ...

  5. 微软 Windows 系统检测网络连通性(用于显示感叹号)竟然是通过访问一个特殊网址来实现的

    一次我走到了弱网环境中,意外地发现浏览器打开了 http://www.msftconnecttest.com/redirect 网址,随后右下角的网络图标出现了一枚“感叹号”.   吹水的推断 从直观 ...

  6. Docker环境下eShopOnContainers部署

    从头开始学eShopOnContainers--Visual Studio 2017环境配置 https://www.cnblogs.com/dusthunter/p/9973815.html 一.安 ...

  7. 剑指offer第二章

    剑指offer第二章 1.二维数组中的查找 在一个二维数组中,每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含 ...

  8. {Reship}{Sparse Representation}稀疏表示

    ===================================================== http://blog.sina.com.cn/s/blog_6d0e97bb01015wo ...

  9. RabbitMQ消息的消费与持久化

    作为消费者的客户端要消费Rabbitmq的消息,首先要建立与它某个队列的连接,具体连接时可指定队列的BindingKey和关系的exchange标识,Rabbitmq判断若已有队列通过BindingK ...

  10. [LeetCode系列] 二叉树最大深度求解问题(C++递归解法)

    问: 给定二叉树, 如何计算二叉树最大深度? 算法描述如下: 如果当前节点为空, 返回0(代表此节点下方最大节点数为0) 如果当前节点不为空, 返回(其左子树和右子树下方最大节点数中的最大值+1) 上 ...