前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Go语言(十五) 反射

Go语言(十五) 反射

作者头像
alexhuiwang
发布2020-09-23 11:39:48
3010
发布2020-09-23 11:39:48
举报
文章被收录于专栏:运维博客

反射

变量介绍

  • 变量的内在机制
    • 类型信息,这部分是元信息,是预先定义好的
    • 值类型,这部分是在程序运行过程中动态改变的

反射介绍

  • 反射与空接口
    • 空接口可以存储任何类型的变量
    • 在程序运行时动态获取变量的类型信息和值信息,就叫反射
代码语言:javascript
复制
import (
   "fmt"
   "reflect"
)

func TestType(a interface{})  {
   //获取类型(静态信息)
   t := reflect.TypeOf(a)
   kind := t.Kind()
   switch kind {
   case reflect.Int:
      fmt.Printf("a is a int\n")
      a = 2
   case reflect.String:
      fmt.Printf("a is a string\n")
   }
   fmt.Printf("t=%v,kind=%v\n\n",t,kind)
}

func TestValue(a interface{}) {
   v := reflect.ValueOf(a)
   //kind := v.Kind()
   t := v.Type()
   switch t.Kind() {
   case reflect.Int:
      fmt.Printf("a is a int\n")
      v.SetInt(10000)
   case reflect.String:
      v.SetString("xxx")
      fmt.Printf("a is a string\n")
   case reflect.Ptr:
      t1 := v.Elem().Type()
      switch (t1.Kind()) {
      case reflect.Int:
         v.Elem().SetInt(100)
         fmt.Printf("ptn is int \n")
      case reflect.String:
         v.Elem().SetString("hello")
         fmt.Printf("ptn is string\n")
      }
      fmt.Printf("a=%v is a point type\n",t1)
   }
   fmt.Printf("v=%v,kind=%v\n\n",v,t)
}

func main() {
   //var a int
   //TestType(a)
   //fmt.Printf("a=%v\n",a)
   //var b string
   //TestType(b)
   var c int
   TestValue(&c)
   var d string
   TestValue(&d)
   fmt.Printf("c=%v, d=%v\n",c,d)
}

结构体反射

代码语言:javascript
复制
type Users struct {
   Name string  `json:"name"`
   Age int
   Sex string
}

//1. 获取a的类型
//2. 我要动态改变a里面存的值
//3. 如果a里面存储的是一个结构体,那可以通过反射获取结构体中的字段信息以及调用结构体里面的方法
func TestValueStruct(a interface{}) {

   v := reflect.ValueOf(a)
   t := v.Type()
   switch t.Kind()  {
   case reflect.Struct:
      fieldNum := t.NumField()
      fmt.Printf("field num:%d\n", fieldNum)
      for i := 0; i <fieldNum; i++{
         field := t.Field(i)
         vField := v.Field(i)

         fmt.Printf("field[%d] name:%s, json key:%s, val:%v\n",
            i, field.Name, field.Tag.Get("json"), vField.Interface())
      }

   }
}
func main()  {
      var user Users
      user.Name = "xxx"
      user.Age = 100
      user.Sex = "man"
      TestValueStruct(user)
      fmt.Printf("user:%#v\n", user)
}

调用结构体中的方法

代码语言:javascript
复制
type S struct {
   A int
   B string
}

func (s *S) Test() {
   fmt.Printf("this is a test\n")
}

func (s *S) SetA (a int) {
   s.A = a
}

func main() {
   s := S{23,"abc"}
   v := reflect.ValueOf(&s)
   m := v.MethodByName("Test")
   var args1 []reflect.Value
   m.Call(args1)
   setA := v.MethodByName("SetA")
   var args2 []reflect.Value
   args2 = append(args2,reflect.ValueOf(100))
   setA.Call(args2)   #修改结构体中的值
   fmt.Printf("s:%#v\n",s)
}

反射总结以及应用场景

  • 总结:
    • 在运行时动态的获取一个变量的类型信息(typeOf)和值信息(valueOf)
  • 应用场景
    • 各种数据库的ORM
      • 配置文件相关的库,比如yaml,ini等
      • 序列化和反序列化,比如json,protoBuf等数据协议

json序列化简版代码

代码语言:javascript
复制
package json_reflect

import (
   "fmt"
   "reflect"
)
func Marshals(data interface{}) (jsonStr string) {

   t := reflect.TypeOf(data)
   v := reflect.ValueOf(data)
   switch t.Kind(){
   case reflect.String,reflect.Int,reflect.Int32:
      jsonStr = fmt.Sprintf("\"%v\"", data)
   case reflect.Struct:
      numField := t.NumField()
      for i := 0; i < numField; i++ {
         //类型信息
         name := t.Field(i).Name
         tag := t.Field(i).Tag.Get("json")
         if len(tag) > 0 {
            name = tag
         }
         //值信息
         vField := v.Field(i)
         vFieldValue := vField.Interface()
         //拼接json
         if t.Field(i).Type.Kind()  == reflect.String {
            jsonStr += fmt.Sprintf("\"%s\":\"%v\"", name, vFieldValue)
         } else {
            jsonStr += fmt.Sprintf("\"%s\":%v", name, vFieldValue)
         }

         if i != numField - 1 {
            jsonStr += ","
         }
      }

      jsonStr = "{" +jsonStr + "}"
   }
   return
}

测试代码

代码语言:javascript
复制
package main

import (
   "fmt"
   "oldBoy/day9/json_reflect"
)

type User struct {
   Name string `json:"name"`
   Age  int    `json:"age"`
   Sex  string `json:"sex"`
}

func main() {
   var a string = "hello abc"
   jsonStr := json_reflect.Marshals(a)
   fmt.Printf(jsonStr)

   var user User
   user.Name = "aaa"
   user.Age = 10
   user.Sex = "male"

   jsonStr = json_reflect.Marshals(user)
   fmt.Printf(jsonStr)
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/04/23 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 反射
    • 变量介绍
      • 反射介绍
        • 结构体反射
          • 调用结构体中的方法
            • 反射总结以及应用场景
            相关产品与服务
            文件存储
            文件存储(Cloud File Storage,CFS)为您提供安全可靠、可扩展的共享文件存储服务。文件存储可与腾讯云服务器、容器服务、批量计算等服务搭配使用,为多个计算节点提供容量和性能可弹性扩展的高性能共享存储。腾讯云文件存储的管理界面简单、易使用,可实现对现有应用的无缝集成;按实际用量付费,为您节约成本,简化 IT 运维工作。
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档