培训首页  >  web前端新闻  >  兄弟连Go语言培训之reflection

兄弟连Go语言培训之reflection

[2018-08-22 15:54:40] 浏览量:49 来源:

北京兄弟连IT

  Go语言经过十余年的发展,已成为最流行的新兴语言。目前,Go语言已成为云计算领域的首选语言,且随着近几年区块链的流行,作为底层开发语言的Go再次火爆成为区块链领域第一编程语言,IBMFabic等重量级的区块链项目都是基于Go语言开发的。

 

  殊不知,Go语言可开发的应用项目还有很多。除云计算、区块链等开源项目外,还包含Devops、人工智能、游戏、存储引擎、Web、系统/命令行工具、中间件、测试/持续交付、文件系统等各方面的开源项目。

 

reflection 反射

 

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

反射使用TypeOfValueOf函数从接口中获取目标对象信息

反射会将匿名字段作为独立字段(匿名字段本质)

想要利用反射修改对象状态,前提是interface.datasettable,pointer-interface

通过反射可以"动态"调用方法

举例

 

1、通过反射来获取属性信息,方法信息

 

//反射  练习

//获取字段的类型信息,方法信息, 属性信息

package main

 

import (

    "fmt"

    "reflect"

)

 

type User struct {

    Id int

    Name string

    Age int

}

 

func (user User) Hello(){

    fmt.Println("hello world")

}

 

func main() {

    user := User{Id:2, Name:"xiaoqiang",Age:30}

    info(user)

}

 

//定义一个方法

//此方法接收的是一个空接口

//这样的话,其实是任何类型都可以接收了

func info(o interface{}) {

    //获取o的类型

    t := reflect.TypeOf(o)

 

    fmt.Println("Type:\t", t.Name())

 

    //取出类型后,需要对类型进行校验,

    //查看是否是规定的类型

    if k :=t.Kind(); k != reflect.Struct {

        //如果不是规定的Struct类型的话,就需要进行

        //异常处理

        fmt.Println("输入参数的类型不匹配!")

        return

    }

 

    //获取o的属性

    v := reflect.ValueOf(o)

    fmt.Println("Fields:\n")

 

    //开始遍历,输出字段

    for i := 0; i < t.NumField(); i++ {

        //获取属性下标

        f := t.Field(i)

        val := v.Field(i).Interface()

        //输出属性的名称,类型,对应的值

        fmt.Printf("%6s:%v = %v\n", f.Name, f.Type, val)

    }

 

    //开始获取 方法的基本信息

    for i:=0; i

        m := t.Method(i)

        fmt.Printf("%6s:%v\n", m.Name, m.Type)

    }

 

}

2、反射是如何 获取 匿名字段呢?

 

//反射 是如何处理 匿名字段的?

package main

 

import (

    "reflect"

    "fmt"

)

 

type Stu struct {

    Id int

    Name string

    Age int

}

 

type Man struct {

    //这里你要注意一下,你创建的属性,是有顺序的,是有下标的

    //Stu 下标 就是0, title下标就是1

    // Stu 就是匿名属性

    Stu

    title string

}

 

func main() {

    //注意,对匿名字段进行初始化时的方式,其实本质上跟其他属性是一样的

    m := Man{Stu:Stu{Id:2,Name:"Jack",Age:19}, title:"Manager"}

    t := reflect.TypeOf(m)

 

    //取匿名字段的方式

    //FieldByIndex 方法,传入的是一个切片slice类型

    //10,表示,匿名字段在Man中的下标位置

    //20,表示,你要取匿名字段中哪个属性的下标

    fmt.Printf("%#v\n", t.FieldByIndex([]int{0,0})) //取的是id

    fmt.Printf("%#v\n", t.FieldByIndex([]int{0,1})) //取的是Name

    fmt.Printf("%#v\n", t.FieldByIndex([]int{0,2})) //取的是Age

 

}

3、通过反射对基本类型进行修改

 

 

//如果通过反射,对基本类型进行修改

package main

 

import (

    "reflect"

    "fmt"

)

 

func main() {

    //下面测试,对基本类型的修改 操作

    x := 456

    //传递的参数是  地址

    v := reflect.ValueOf(&x)

 

    //Elem方法,是取出元素值来,然后通过setint方法,进行重新设置

    v.Elem().SetInt(789)

 

    fmt.Println(x)

}

4、通过反射 对复杂类型进行修改

 

//如果通过反射,对复杂类型进行修改

package main

 

import (

    "reflect"

    "fmt"

)

 

type Teac struct {

    Id int

    Name string

    Age int

}

 

func main() {

    teac := Teac{Id:5,Name:"Ant-man",Age:23}

    fmt.Println("teac:\t", teac)

    //传递的是 地址哦

    Set(&teac)

    fmt.Println("teac:\t", teac)

}

 

func Set(o interface{}) {

    v := reflect.ValueOf(o)

    if v.Kind() == reflect.Ptr && !v.Elem().CanSet() {

        fmt.Printf("xxx")

        return

    }else{

        v = v.Elem()

    }

 

    // 通过FieldByName 这个方法,直接输入 名称,来获取

    f := v.FieldByName("Name")

 

    //校验,是否取到Name属性的值

    if !f.IsValid() {

        fmt.Printf("BAD")

        return

    }

 

    //然后,再校验,类型是否匹配

    if f.Kind() == reflect.String {

        f.SetString("Iron Man")

    }

 

}

5、通过反射对方法进行动态调用

 

//通过反射,进行方法的调用,相当于动态调用了

package main

 

import (

    "fmt"

    "reflect"

)

 

type Teacher struct {

    Id int

    Name string

    Age int

}

 

//通过receiverShow方法,跟Teacher类型,进行绑定

func (teacher Teacher)Show(name string) {

    fmt.Println("hello, ", name, ", my name is ", teacher.Name)

}

 

//注意======目前没有发现====如何通过====反射===来获取=====私有方法

func (teacher Teacher)info(){

    fmt.Println("=====")

}

 

func main() {

    teacher := Teacher{Id:34, Name:"Thor",Age:34}

    teacher.Show("Hawkeye")

 

    //下面通过反射,调用show方法

    v := reflect.ValueOf(teacher)

    //获取show方法

    m := v.MethodByName("Show")

 

    //校验一下,是否获取到show方法呢

    if !m.IsValid() {

        fmt.Printf("=======没有获取到制定的方法====")

        return

    }

 

    //参数必须是切片类型

    //reflect.Value{}   这里面,可以设定多个参数类型

    //目前,我们这里只有一个string类型的参数

    //

    args := []reflect.Value{reflect.ValueOf("Hulk")}

    m.Call(args)

}

高能预警,兄弟连教育区块链直播课程8月持续火爆来袭!

原价1188元的12节区块链进阶课程,现仅需1元!

  • 软件开发
  • 软件测试
  • 数据库
  • Web前端
  • 大数据
  • 人工智能
  • 零基础
  • 有HTML基础
  • 有PHP基础
  • 有C语言基础
  • 有JAVA基础
  • 其他计算机语言基础
  • 周末班
  • 全日制白班
  • 随到随学