首页 > 其他分享 >golang反射reflect

golang反射reflect

时间:2022-08-21 20:56:36浏览次数:54  
标签:reflect 反射 fmt golang json func main Type

1 reflect包

reflect包实现了运行时反射,允许程序操作任意类型的对象。典型用法是用静态类型interface{}保存一个值,通过调用TypeOf获取其动态类型信息,该函数返回一个Type类型值。调用ValueOf函数返回一个Value类型值,该值代表运行时的数据。Zero接受一个Type类型参数并返回一个代表该类型零值的Value类型值。

①对基本数据类型进行反射:

package main

import (
   "fmt"
   "reflect"
)

func reflectNum(arg interface{}) {
   fmt.Println("value:", reflect.ValueOf(arg))
   fmt.Println("type:", reflect.TypeOf(arg))
}

func main() {
   var num float64 = 1.2334
   reflectNum(num)
}

控制台输出:

value: 1.2334
type: float64

②对结构体类型进行反射:

package main

import (
   "fmt"
   "reflect"
)

type User struct {
   Id   int
   Name string
   Age  int
}

func (u User) Call() {
   fmt.Println("User is called ..")
   fmt.Printf("%v\n", u)
}

func DoFieldAndMethod(i interface{}) {
   //获取input的type
   inputType := reflect.TypeOf(i)
   fmt.Println("inputType is :", inputType.Name()) //Type类的Name()方法可以直接返回当前类型的名称

   //获取input的value
   inputValue := reflect.ValueOf(i)
   fmt.Println("inputValue is :", inputValue)

   //通过Type类和Value类对结构体的字段进行访问
   for i := 0; i < inputType.NumField(); i++ { //Type类的NumField()方法返回当前类型属性的个数
      field := inputType.Field(i)              //Type类的Field(i int)方法返回当前类的第i个字段
      value := inputValue.Field(i).Interface() //通过Value类的Field()拿到当前类的第i个字段,再通过Interface()返回v当前持有的值(表示为/保管在interface{}类型)

      fmt.Printf("%s : %v = %v\n", field.Name, field.Type, value)
   }

   //通过type获取里面的方法
   for i := 0; i < inputType.NumMethod(); i++ { //Type类的NumMethod()方法返回当前类型方法的个数
      m := inputType.Method(i)
      fmt.Printf("%s : %v\n", m.Name, m.Type)
   }
}

func main() {
   user := User{1, "liam", 23}
   //fmt.Println(reflect.ValueOf(user).Field(1).Interface())
   DoFieldAndMethod(user)
}

控制台输出:

inputType is : User
inputValue is : {1 liam 23}
Id : int = 1
Name : string = liam
Age : int = 23
Call : func(main.User)

2 反射解析结构体标签Tag

可以在结构体字段后用“ `` ”来对字段添加说明标签:

type resume struct {
	Name   string `info:"name" doc:"我的名字"`
	Gender rune   `info:"gender"`
}

可以通过反射来访问结构体字段的Tag:

package main

import (
   "fmt"
   "reflect"
)

type resume struct {
   Name   string `info:"name" doc:"我的名字"`
   Gender rune   `info:"gender"`
}

func findTag(str interface{}) {
   t := reflect.TypeOf(str).Elem()

   for i := 0; i < t.NumField(); i++ {
      tagInfo := t.Field(i).Tag.Get("info")
      tagDoc := t.Field(i).Tag.Get("doc")
      fmt.Println("info:", tagInfo, "doc:", tagDoc)
   }
}

func main() {
   var re resume
   findTag(&re)
}

控制台输出:

info: name doc: 我的名字
info: gender doc: 

2.1 结构体标签在json中的应用

可以通过encoding/json包来将结构体和json格式相互转换:

package main

import (
   "encoding/json"
   "fmt"
)

type Movie struct {
   Title  string   `json:"title"`
   Year   int      `json:"year"`
   Price  int      `json:"rmb"`
   Actors []string `json:"actors"`
}

func main() {
   movie := Movie{
      Title:  "CatchMeIfYouCan",
      Year:   2002,
      Price:  20,
      Actors: []string{"Leonardo", "TomHanks"},
   }
   //编码过程:结构体--->json
   jsonStr, err := json.Marshal(movie)
   if err != nil {
      fmt.Println("json marshal err:", err)
      return
   }
   fmt.Printf("%s\n", jsonStr)

   //解码过程:json--->结构体
   myMovie := Movie{}
   err = json.Unmarshal(jsonStr, &myMovie)
   if err != nil {
      fmt.Println("json unmarshal err:", err)
      return
   }
   fmt.Printf("%v\n", myMovie)
}

控制台输出:

{"title":"CatchMeIfYouCan","year":2002,"rmb":20,"actors":["Leonardo","TomHanks"]}
{CatchMeIfYouCan 2002 20 [Leonardo TomHanks]}

标签:reflect,反射,fmt,golang,json,func,main,Type
From: https://www.cnblogs.com/SpriteLee/p/16610845.html

相关文章

  • C++反序列化--一种基于class infomation反射库的反序列化数据结构
    序列化与反序列化概念:将程序的某些数据存储在内存中,然后将其写入某个文件或是将它传输到网络中的另一台计算机上以实现通讯。这个将程序数据转化成能被存储并传输的格式的......
  • golang 值类型与引用类型
    转自:https://www.zhihu.com/search?type=content&q=golang%20%20%E5%80%BC%E7%B1%BB%E5%9E%8B%E3%80%81%E5%BC%95%E7%94%A8%E7%B1%BB%E5%9E%8B%E3%80%81%E6%8C%87%E9%92%88......
  • Golang学习(二)
    12.单元测试12.1引入在我们工作中有时需要去确认一个函数或者一个模块的结果是否正确,如:  12.2传统的方法解决问题在main函数中调用addUpper函数,看看实际输出结果......
  • Golang中slice操作的一些坑
    packagego_testsimport("bytes""fmt""testing")//0、引用类型funcTestT0(t*testing.T){s1:=[]int{1,2,3}f1:=func(s[]int......
  • Notepad plus 通过NppExec插件编译/运行 golang,php,python等语言
        1. 在Notepadplus的插件-->插件管理中,添加nppExec插件。          2.打开插件-->NppExec,选择Showconsole,和Follow($CURRE......
  • Java的反射
    在我们平时的开发中,我们肯定会遇到过spring框架。框架中我们几乎不需要手动去new对象。只需要通过一些简单的配置,spring就会把对象为我们创建好。这里就用到反射。下面我......
  • golang编译问题
    golangmain包下推荐只有一个main.go的入口文件当有其他的go文件,并且在其他go文件中定义了函数 在main.go入口文件中调用了该函数,执行gorunmain.go,会提示unde......
  • Golang基础教程
    以下使用goland的IDE演示,包含总计的golang基础功能共20个章节一、go语言结构:二、go基础语法:三、变量四、常量五、运算符六、条件语句七、循环八、函数九、变量......
  • golang中GOPATH、GOROOT、GOBIN不生效等相关问题
    比较重要的三个配置:GOPATH、GOROOT、GOBINGOPATH:go项目开发的工程目录GOROOT:go安装所在的目录GOBIN:go项目编译完二进制程序目录不生效问题,其实应该好好检查是否......
  • python 动态导入模块并结合反射,动态获取类、方法(反射太好用)
    背景: 关键字驱动框架,不同的关键字方法分别定义在不同的类,真正执行关键字方法又在不同的类(简称A),这样就需要在执行前,要在文件A下import要使用的模块,如果有很多页面操作或很......