咔叽游戏

 找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 448|回复: 0

[Golang] Go语言基础反射示例详解

[复制链接]
  • TA的每日心情
    无聊
    2019-6-2 14:11
  • 签到天数: 4 天

    [LV.2]圆转纯熟

    发表于 2022-1-1 10:58:22 | 显示全部楼层 |阅读模式
    目录

      概述语法
        一、基本操作二、修改目标对象三、动态调用方法
      总结示例

    Go语言基础反射示例详解-1.png


    概述

    在程序运行期对程序动态的进行访问和修改
    reflect godoc: https://golang.org/pkg/reflect/
    reflect包有两个数据类型:
    Type:数据类型 【reflect.TypeOf():是获取Type的方法】
    Value:值的类型【reflect.ValueOf():是获取Value的方法】

    语法


    一、基本操作

    获取变量类型
    1. func TypeOf(i interface{}) Type   //Type是interface{}的别名
    复制代码
    例子
    1. reflect.TypeOf(10)  //int
    2. reflect.TypeOf(struct{ age int }{10})  //struct { age int }
    复制代码
    获取变量的种类
    1. reflect.TypeOf(struct{ age int }{10}).Kind()  //reflect.Struct
    2. reflect.ValueOf("hello word").Kind()  //reflect.String
    复制代码
    获取变量值
    1. func ValueOf(i interface{}) Value   //value是struct {}别名
    复制代码
    例子
    1. reflect.ValueOf("hello word")  //hello word
    2. reflect.ValueOf(struct{ age int }{10})   //{10}
    复制代码
    二、修改目标对象

    修改普通类型
    1. str := "hello word"
    2. reflect.ValueOf(&str).Elem().SetString("张三")
    复制代码
    修改结构体
    1. //第一步:ValueOf():传入一个变量的地址,返回是变量的地址     Elem():返回的是变量的原始值
    2. elem:=reflect.ValueOf(&变量名).Elem()
    3. //第二步 FieldByName():传入结构体字段名称   SetString():传入你要修改的变量值
    4. elem.FieldByName("Name").SetString("李四")
    复制代码
    1. //定义一个User结构体
    2. type User struct {
    3.         Name string
    4.         Age  int
    5. }
    6. user := User{Name: "张三", Age: 10}
    7. //Elem() 获取user原始的值
    8. elem := reflect.ValueOf(&user).Elem()
    9. //FieldByName() 通过Name返回具有给定名称的结构字段 通过SetString 修改原始的值
    10. elem.FieldByName("Name").SetString("李四")
    11. elem.FieldByName("Age").SetInt(18)
    复制代码
    三、动态调用方法

    无参方法
    1. //MethodByName():传方法名,方法名必须大小  Call():方法的形参
    2. reflect.ValueOf(变量名).MethodByName(方法名).Call([]reflect.Value{})
    3. reflect.ValueOf(变量名).MethodByName(方法名).Call(make([]reflect.Value, 0))
    复制代码
    1. type User struct {
    2.         Name string `json:"name" name:"张三"`
    3.         Age  int
    4. }
    5. func (_ User) Say() {
    6.         fmt.Println("user 说话")
    7. }
    8. user := User{Name: "张三", Age: 10}
    9. reflect.ValueOf(&user).MethodByName("Say").Call([]reflect.Value{})
    10.   reflect.ValueOf(user).MethodByName("Say").Call(make([]reflect.Value, 0))
    复制代码
    有参方法
    1. reflect.ValueOf(变量名).MethodByName(方法名).Call([]reflect.Value{reflect.ValueOf("该说话了"), reflect.ValueOf(1)})
    复制代码
    1. type User struct {
    2.   Name string `json:"name" name:"张三"`
    3.   Age  int
    4. }
    5. func (_ User) Say() {
    6.   fmt.Println("user 说话")
    7. }
    8. user := User{Name: "张三", Age: 10}
    9. reflect.ValueOf(user).MethodByName("SayContent").Call([]reflect.Value{reflect.ValueOf("该说话了"), reflect.ValueOf(1)})
    复制代码
    总结

    反射调用struct的方法必须是公有的
    反射调用无参方法时必修传 nil 或者 []reflect.Value{}

    示例
    1. package main
    2. import (
    3.         "fmt"
    4.         "reflect"
    5. )
    6. func main() {
    7.         //1. 获取变量类型
    8.         fmt.Println("获取变量类型")
    9.         fmt.Println(reflect.TypeOf(10))                          //int
    10.         fmt.Println(reflect.TypeOf(10.0))                        //float64
    11.         fmt.Println(reflect.TypeOf(struct{ age int }{10}))       //struct { age int }
    12.         fmt.Println(reflect.TypeOf(map[string]string{"a": "a"})) //map[string]string
    13.         fmt.Println("")
    14.         //2. 获取变量值
    15.         fmt.Println("获取变量值")
    16.         fmt.Println(reflect.ValueOf("hello word"))                //hello word
    17.         fmt.Println(reflect.ValueOf(struct{ age int }{10}))       //{10}
    18.         fmt.Println(reflect.TypeOf(struct{ age int }{10}).Kind()) //struct
    19.         //类型判断
    20.         if t := reflect.TypeOf(struct{ age int }{10}).Kind(); t == reflect.Struct {
    21.                 fmt.Println("是结构体")
    22.         } else {
    23.                 fmt.Println("不是结构体")
    24.         }
    25.         //修改目标对象
    26.         str := "hello word"
    27.         //普通变量修改
    28.         reflect.ValueOf(&str).Elem().SetString("张三")
    29.         fmt.Println(str)
    30.         //结构体变量修改
    31.         user := User{Name: "张三", Age: 10}
    32.         //Elem() 获取user原始的值
    33.         elem := reflect.ValueOf(&user).Elem()
    34.         //FieldByName() 通过Name返回具有给定名称的结构字段 通过SetString 修改原始的值
    35.         elem.FieldByName("Name").SetString("李四")
    36.         elem.FieldByName("Age").SetInt(18)
    37.         fmt.Println(user)
    38.         //获取结构体的标签的值
    39.         fmt.Println(reflect.TypeOf(&user).Elem().Field(0).Tag.Get("name"))
    40.         //调用无参方法
    41.         reflect.ValueOf(&user).MethodByName("Say").Call([]reflect.Value{})
    42.         reflect.ValueOf(user).MethodByName("Say").Call(make([]reflect.Value, 0))
    43.         //调用有参方法
    44.         reflect.ValueOf(user).MethodByName("SayContent").Call([]reflect.Value{reflect.ValueOf("该说话了"), reflect.ValueOf(1)})
    45.         //调用本地的方法
    46.         reflect.ValueOf(Hello).Call([]reflect.Value{})
    47.         reflect.ValueOf(Hello).Call(nil)
    48.         fmt.Printf("%#v\n", reflect.TypeOf(user).Field(0))
    49. }
    50. func Hello() {
    51.         fmt.Println("hello")
    52. }
    53. type Person struct {
    54.         Name string
    55. }
    56. type User struct {
    57.         Person        // //反射会将匿名字段作为一个独立字段来处理
    58.         Name   string `json:"name" name:"张三"`
    59.         Age    int
    60. }
    61. func (_ User) Say() {
    62.         fmt.Println("user 说话")
    63. }
    64. func (_ User) SayContent(content string, a int) {
    65.         fmt.Println("user", content, a)
    66. }
    复制代码
    以上就是Go语言基础反射示例详解的详细内容,更多关于Go语言反射的资料请关注咔叽论坛其它相关文章!

    原文地址:https://www.jb51.net/article/229367.htm

    QQ|免责声明|小黑屋|手机版|Archiver|咔叽游戏

    GMT+8, 2024-3-28 23:24

    Powered by Discuz! X3.4

    © 2001-2023 Discuz! Team.

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