Go语言(十五) 反射

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

反射

变量介绍

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

反射介绍

  • 反射与空接口
    • 空接口可以存储任何类型的变量
    • 在程序运行时动态获取变量的类型信息和值信息,就叫反射
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)
}

结构体反射

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)
}

调用结构体中的方法

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序列化简版代码

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
}

测试代码

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)
}

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

本文来自:51CTO博客

感谢作者:wx5b285b48ed74e

查看原文:Go语言(十五) 反射

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

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