一篇文章教会你Go语言基础之结构体反射

mb6066e504cce6f · · 289 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

前言

Hey,大家好呀,我是码农,星期八。

反射在结构体中的应用,才是最广泛的!毕竟在Go中,是用结构体代替对象的!

所以最多的,最麻烦的,也是反射结构体,也是最灵活的!


反射在结构体的应用

上次讲的,只是在普通变量中的应用,相对来说,使用的场景不是太多。

但是反射在结构体中的应用,基本会贯穿整个Go语言基础。

示例代码

结构体

type Student struct {    Name   string   `json:"name" describe:"姓名"`    Age    int      `json:"age" describe:"年龄"`    Gender bool     `json:"gender" describe:"性别"`    Hobby  []string `json:"hobby" describe:"爱好"`}

main

func main() {    //实例化结构体    var s1 = Student{        Name:   "张三"        Age:    18        Gender: true        Hobby:  []string{"吃""喝""pia""玩"},}    var t = reflect.TypeOf(s1)    fmt.Println(t.Name())     //Student    fmt.Println(t.Kind())     //struct    fmt.Println(t.NumField()) //结果:4,表示多少个字段    for i := 0; i < t.NumField(); i++ {        field := t.Field(i)//每个结构体对象        /*            {Name  string json:"name" describe:"姓名" 0 [0] false}            {Age  int json:"age" describe:"年龄" 16 [1] false}            {Gender  bool json:"gender" describe:"性别" 24 [2] false}            {Hobby  []string json:"hobby" describe:"爱好" 32 [3] false}        */        //fmt.Println(field)        fmt.Println("------")        fmt.Printf("field.Name:%v\n",field.Name)        fmt.Printf("field.Index:%v\n",field.Index)        fmt.Printf("field.Type:%v\n",field.Type)        fmt.Printf("field.Tag:%v\n",field.Tag.Get("describe"))
   }}

执行结果

单独反射指定字段信息

main代码

func main() {    //实例化结构体    var s1 = Student{        Name:   "张三",        Age:    18,        Gender: true,        Hobby:  []string{"吃", "喝", "pia", "玩"},}    var t = reflect.TypeOf(s1)    genderField, ok := t.FieldByName("Gender")    if ok {        fmt.Println(genderField.Name)                //Gender        fmt.Println(genderField.Index)               //[2]        fmt.Println(genderField.Type)                //bool        fmt.Println(genderField.Tag.Get("describe")) //性别    }}

ValueOf

上述的代码只能用的是TypeOf,只能返回类型等信息,相对来说不是太智能,ValueOf可以获取值,同样也能获取类型,相对来说比TypeOf好一点。

示例代码

main

func main() {    //实例化结构体    var s1 = Student{        Name:   "张三",        Age:    18,        Gender: true,        Hobby:  []string{"吃", "喝", "pia", "玩"},}    var v = reflect.ValueOf(s1)    for i := 0; i < v.NumField(); i++ {        field :=v.Field(i)        fmt.Println("------")        fmt.Printf("Kind:%v\n",field.Kind())        fmt.Printf("值:%v\n",field.Interface())    }}

执行结果


反射方法

上述我们反射的都是值,有没有反射是否可以反射函数,并且调用函数呢??

结构体和绑定函数代码

type Student struct {    Name   string   `json:"name" describe:"姓名"`    Age    int      `json:"age" describe:"年龄"`    Gender bool     `json:"gender" describe:"性别"`    Hobby  []string `json:"hobby" describe:"爱好"`}
//无参方法func (this Student) Say() {    fmt.Printf("我是%v,我的年龄是%v,我的性别是%v,我的爱好是%v\n"this.Name, this.Age, this.Gender, this.Hobby)}//有参数方法func (this Student) Jump(distance int) {    fmt.Printf("我是%v,我跳远跳了%v米\n"this.Name, distance)}

main

func main() {    //实例化结构体    var s1 = Student{        Name:   "张三",        Age:    18,        Gender: true,        Hobby:  []string{"吃", "喝", "pia", "玩"},}    var t = reflect.TypeOf(s1)    var v = reflect.ValueOf(s1)    fmt.Println(v.NumMethod(),v.NumField())    for i := 0; i < v.NumMethod(); i++ {        method := v.Method(i)        fmt.Println("--------")        fmt.Println(method)//0x48c4e0 函数地址        fmt.Println(method.Type())//func(int) 函数类型,形参和返回值        fmt.Println(t.Method(i).Name)//Jump,函数名,注意,由t来调用的    }}

执行结果

图片


反射调用函数

func main() {    //实例化结构体    var s1 = Student{        Name:   "张三"        Age:    18        Gender: true        Hobby:  []string{"吃""喝""pia""玩"},}    var v = reflect.ValueOf(s1)
   //通过反射调用函数    //调用Jump函数    //反射调用函数必须传一个参数,不管有没有形参都要传    //var args = []reflect.Value{}    //v.MethodByName("Say").Call(args)
   //如果需要传参数    //参数需要用reflect.ValueOf(1) 强转一下
   var args = []reflect.Value{reflect.ValueOf(2)}    v.MethodByName("Jump").Call(args)}

注:注意第14行和20行代码区别,如果要传参数,参考第20行代码。

执行结果

图片


反射注意事项

在平常开发中,尽量慎用反射,原因如下。

  • 反射性能可能会比较低,毕竟是反正走的,一般比正向操作慢一两个级别。

  • 反射越多,代码越烂,TypeOfValueOf都有Kind,很多情况是TypeOfValueOf混用的,所以对于基础不好的,极不友好。

  • 在Go中,是没有try的,如果反射没有处理好异常,程序会直接崩溃,可能在意想不到的地方。



有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:mb6066e504cce6f

查看原文:一篇文章教会你Go语言基础之结构体反射

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

289 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传