反射的知识点比较晦涩,后期会对此知识点展开深入的分析及示例代码展示

  • 反射可达大提高程序的灵活性,使得inferface{}有更大的发挥余地

  • 反射使用TypeOf和ValueOf函数从接口中获取目标对象信息:字段属性,方法信息

    package main
    import (
    "fmt"
    "reflect"
    )
    type User struct { //定义一个结构类型
    Id int
    Name string
    Age int
    } func (u User) Hello() { //定义一个结构方法
    fmt.Println("Hello world")
    } func Info(o interface{}) { //定义一个方法,参数为空接口
    t := reflect.TypeOf(o) //获取接收到的接口类型
    fmt.Println("Type:", t.Name()) //获取名称 v := reflect.ValueOf(o) //获取接口的字段
    fmt.Println("Fields:") //获取结构字段
    for i := 0; i < t.NumField(); i++ { //for循环,取出所拥有的字段
    f := t.Field(i) //获取值字段
    val := v.Field(i).Interface() //获取字段的值
    fmt.Printf("%6s:%v=%v\n", f.Name, f.Type, val)
    }
    //通过接口获取结构的方法
    for i := 0; i < t.NumMethod(); i++ {
    m := t.Method(i)
    fmt.Printf("%6s:%v\n", m.Name, m.Type)
    } } func main() {
    u := User{1, "OK", 12} //实例化一个结构
    Info(u) //调用Info函数 } /*输出
    Type: User
    Fields:
    Id:int=1
    Name:string=OK
    Age:int=12
    Hello:func(main.User)
    */
  • 反射会将匿名字段作为独立字段(匿名字段本质)

    package main
    import (
    "fmt"
    "reflect"
    ) type User struct { //定义一个结构类型
    Id int
    Name string
    Age int
    } type Manager struct {
    User //嵌入User结构,User就是Manager结构的匿名字段
    title string
    } func main() {
    m := Manager{User: User{1, "mm", 27}, title: "name"} //注意初始化方式
    t := reflect.TypeOf(m) //传递结构 fmt.Printf("%#v\n", t.Field(0)) //获取索引为0的字段信息,即User字段信息
    fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 0})) //根据索引取出ID的字段信息()
    } //{0,0}--User在Manager索引为0,ID在User索引为0 /*output
    reflect.StructField{Name:"User", PkgPath:"", Type:(*reflect.rtype)(0x4ac220), Tag:"",
    Offset:0x0, Index:[]int{0}, Anonymous:true} "Anonymous:true" 其中包含Anonymous(匿名)字段
    */
  • 想要利用反射修改对象状态,前提是interface.data是settable,即pointer-interface(指针接口)

    • 示例1
    //这是一个简单的修改对象状态
    package main
    import (
    "fmt"
    "reflect"
    ) func main() {
    x := 123 //底层类型是int类型
    v := reflect.ValueOf(&x) //传递x的指针
    v.Elem().SetInt(999) //通过方法修改x变量的值 fmt.Println(x)
    } /*输出
    x---> 999
    */
    • 示例2
    //通过反射修改结构字段
    package main
    import (
    "fmt"
    "reflect"
    ) type User struct {
    Name string
    ID int
    Age int
    } func main() {
    u := User{"MAOZI", 1, 22}
    Set(&u)
    fmt.Println(u) } func Set(o interface{}) {
    v := reflect.ValueOf(o) if v.Kind() != reflect.Ptr && !v.Elem().CanSet() { //判断是否为反射typestring,且可以被修改
    fmt.Println("fuck")
    return
    } else { //如果条件都满足
    v = v.Elem()
    } f := v.FieldByName("Name") //通过名字段名找字段
    if !f.IsValid() { //IsValid方法判断是否找了字段
    fmt.Println("invalid")
    return
    }
    if f.Kind() == reflect.String {
    f.SetString("momo")
    } } /*输出
    {momo 1 22}
    */
  • 通过反射可以"动态"调用方法

    //通过反射动态调用结构方法
    package main
    import (
    "fmt"
    "reflect"
    ) type User struct {
    Name string
    ID int
    Age int
    } func (u User) Hello(name string) {
    fmt.Println("Hello", name, ",my name is", u.Name) }
    func main() {
    u := User{"Golang", 1, 22}
    v := reflect.ValueOf(u)
    mv := v.MethodByName("Hello") //反射:通过名字找结构字段信息 args := []reflect.Value{reflect.ValueOf("Python")}
    mv.Call(args) } /*输出
    Hello Python ,my name is Golang
    */

golang基础--reflect反射的更多相关文章

  1. golang:reflect反射

    因为之前一直以C++为主要开发语言,所以刚接触go语言中的reflect时感觉很懵逼,因此决定找资料彻底学习一下. 到底反射是什么? https://blog.golang.org/laws-of-r ...

  2. golang 使用reflect反射结构体

    "反射结构体"是指在程序执行时,遍历结构体中的字段以及方法. 1.反射结构体 下面使用一个简单的例子说明如何反射结构体. 定义一个结构体,包括3个字段,以及一个方法. 通过refl ...

  3. golang 通过reflect反射修改值

    不是所有的反射值都可以修改.对于一个反射值是否可以修改,可以通过CanSet()进行检查. 要修改值,必须满足: 可以寻址 可寻址的类型: 指针指向的具体元素 slice的元素 可寻址的结构体的字段( ...

  4. golang中的反射reflect详解

    先重复一遍反射三定律: 1.反射可以将"接口类型变量"转换为"反射类型对象". 2.反射可以将"反射类型对象"转换为"接口类型变量 ...

  5. Go语言基础之反射

    Go语言基础之反射 本文介绍了Go语言反射的意义和基本使用. 变量的内在机制 Go语言中的变量是分为两部分的: 类型信息:预先定义好的元信息. 值信息:程序运行过程中可动态变化的. 反射介绍 反射是指 ...

  6. Golang 接口与反射知识要点

    目录 Golang 接口与反射知识要点 1. 接口类型变量 2. 类型断言 3. 鸭子类型 4. 反射机制 5. reflect 包 TypeOf().ValueOf() Type().Kind() ...

  7. GO学习-(17) Go语言基础之反射

    Go语言基础之反射 本文介绍了Go语言反射的意义和基本使用. 变量的内在机制 Go语言中的变量是分为两部分的: 类型信息:预先定义好的元信息. 值信息:程序运行过程中可动态变化的. 反射介绍 反射是指 ...

  8. Golang 基础之基础语法梳理 (三)

    大家好,今天将梳理出的 Go语言基础语法内容,分享给大家. 请多多指教,谢谢. 本次<Go语言基础语法内容>共分为三个章节,本文为第三章节 Golang 基础之基础语法梳理 (一) Gol ...

  9. 黑马程序员:Java基础总结----反射

    黑马程序员:Java基础总结 反射   ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 反射 反射的基石:Class类 Class类代表Java类,它的各个实例对象又分别 ...

随机推荐

  1. [ACM_水题] UVA 12502 Three Families [2人干3人的活后分钱,水]

      Three Families  Three families share a garden. They usually clean the garden together at the end o ...

  2. LayaAir从入门到放弃

    我是一个小白程序员,准备开发小程序找了很久小程序开发引擎,看到白鹭和LayaAir .经过一番资料查找后被LayaAir高性能.接口简洁及社区活跃所吸引,然后选择了LayaAir. 开发过程中一般小问 ...

  3. Xml 序列化和反序列化

    xml序列化帮助类 using System.IO; using System.Xml; using System.Xml.Serialization; public class XmlHelper ...

  4. Java的8种基本数据类型

    待整理主题:Java的8种基本数据类型与对应封装类型.拆箱.装箱 =================================================================== ...

  5. 使用putty连接本地VirtualBox上的centos7 linux主机

    1. 查看linux主机默认ssh端口 因为是使用ssh连接虚拟机上的linux主机的,所以需要查看centos ssh默认端口,一般是22 打开终端 输入cd /etc/ssh/ 查看ssh_con ...

  6. 基于Spring Boot的Logback日志轮转配置

    在生产环境下,日志是最好的问题调试和跟踪方法,因此日志的地位是十分重要的.我们平时经常使用的log4j,slf4j,logback等等,他们的配置上大同小异.这里就结合Spring Boot配置一下L ...

  7. java的几种定时任务

    本篇博文主要是讲述2.x 版本的quartz下的实现方案,1.x 版本的实现方式大致原理一致,但是具体的实现方式有些不一致,具体体现在获取  scheduler 这个类的方式上有些不同,这里不作过多的 ...

  8. java.lang.IllegalStateException: BeanFactory not initialized or already closed - call 'refresh' before accessing beans via the ApplicationContext

    spring的项目中有时候会报错:java.lang.IllegalStateException: BeanFactory not initialized or already closed - ca ...

  9. ThreadLocal模式与synchronized关键字的比较

    ThreadLocal模式与synchronized关键字都是用于处理多线程并发访问变量的问题.只是两者处理问题的角度和思路不同. 1)ThreadLocal是一个Java类,通过对当前线程(Thre ...

  10. iOS-UIView一些坐标和位置方法封装

    新建基于UIView扩展类 UIView+wkjFrame,此类是为了方便获取一些基于UIView类UI控件的坐标和位置的简化,直接引用即可 UIView+wkjFrame.h - (CGPoint) ...