深入了解Golang中reflect反射的使用

 更新时间:2023年05月11日 11:42:28   作者:未来谁可知  
这篇文章主要介绍了深入了解Golang中reflect反射的使用,Go语言中的反射是一种机制,可以在运行时动态地获取类型信息和操作对象,以及调用对象的方法和属性等,需要详细了解可以参考下文

1. 介绍

在反射的世界里,我们拥有了获取一个对象的类型,属性及方法的能力。

在 Go 反射的世界里,有两种类型非常重要,是整个反射的核心,在学习 reflect 包的使用时,先得学习下这两种类型:

  • reflect.Type
  • reflect.Value

2. 方法示例

2.1 通过反射获取对象的键(类型)和值

package main
import (
   "fmt"
   "reflect"
)
//
func reflectNum(arg interface{})  {
   fmt.Println("type:",reflect.TypeOf(arg))
   fmt.Println("value : ",reflect.ValueOf(arg))
}
func main() {
   reflectNum(1.1234)
}

type: float64
value : 1.1234

注意,Go 中所有对象都是键+值组成的,含有这种特性的对象都是可以用 Type + Value 进行抽象的,这就是万能对象

2.2 反射对象的类型和属性

package main
import (
   "fmt"
   "reflect"
)
type User struct {
   Id int
   Name string
   Age int
}
func (this User) Call()  {
   fmt.Println("user is called ..")
   fmt.Printf("#{this}\n")
}
func main() {
   user := User{1,"Aceld",18}
   //传入 user 对象
   DoFiledAndMethod(user)
}
//接收万能对象 用反射解析
func DoFiledAndMethod(input interface{})  {
   //反射获取类的类型
   inputType := reflect.TypeOf(input)
   fmt.Println("inputType is :", inputType.Name() )
  // inputType is : User
   inputValue := reflect.ValueOf(input)
   fmt.Println("inputValue is :", inputValue)
  //inputValue is : {1 Aceld 18}
   //反射获取类的属性
   for i := 0; i < inputType.NumField(); i++ {
      field := inputType.Field(i)
      value := inputValue.Field(i).Interface()
      fmt.Printf("%s : %v = %v\n",field.Name,field.Type,value)
      //Id : int = 1
      //Name : string = Aceld
      //Age : int = 18
   }
   //反射调用方法
   for i := 0; i < inputType.NumMethod(); i++ {
      m := inputType.Method(i)
      //%s 输出字符串表示(string类型或[]byte)
      //%v  相应值的默认格式。
      fmt.Printf("%s:%v\n",m.Name,m.Type)
     //Call:func(main.User)
   }
}

3. 反射对Json的操作

3.1 反射与Json属性解析

在结构体属性中 我们可以通过加 tag 以供其他程序的解析与识别

package main
import (
   "fmt"
   "reflect"
)
type resume struct {
   // ':'前后不加空格  ` != '
   Name string `info:"name"  doc:"我的名字" `
   Sex string `info:"sex" `
}
func findTag(str interface{})  {
   // Elem returns a type's element type.
   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: sex doc:

3.2 Json包的序列化与反序列化

go 的 json 工具要想解析 需要你在字段上添加 json tag

package main
import (
   "encoding/json"
   "fmt"
)
// 全部添加 json 的 tag
type Movie struct {
   Title string `json:"title"`
   Year int `json:"year"`
   Price int `json:"rmb"`
   Actors []string `json:"actors"`
}
func main() {
   movie := Movie{"喜剧之王", 2000, 10, []string{"zhouxingchi", "wumengda"}}
   // 序列化
   jsonStr, err := json.Marshal(movie)
   if err != nil {
      fmt.Println("json marshal error",err)
      return
   }
   fmt.Printf("jsonStr = %s\n",jsonStr)
   //反序列化
   m := Movie{}
   err = json.Unmarshal(jsonStr, &m)
   if err != nil {
      fmt.Println("json ummarshal error", err)
      return
   }
   fmt.Printf("%v\n",m)
}

4. 实战巩固

4.1 需求

​ 项目经常会在启动的时候会加一些环境变量参数,随着启动而触发作用加载到项目中,现如今在。利用os包设置好环境变量,利用反射实现项目启动时运行时加载进环境!

环境变量KeyCONFIG_SERVER_NAMECONFIG_SERVER_IPCONFIG_SERVER_URL

4.2 代码实现

package main
import (
	"fmt"
	"os"
	"reflect"
	"strings"
)
type Config struct {
	Name    string `json:"server-name"`
	IP      string `json:"server-ip"`
	URL     string `json:"server-url"`
	Timeout string `json:"timeout"`
}
func readConfig() *Config {
	// read from xxx.json,省略
	config := Config{}
	// 1. 拿到config的反射类型
	typ := reflect.TypeOf(config)
	// 2. 拿到config的反射值对象
	value := reflect.Indirect(reflect.ValueOf(&config))
	// 3. 遍历每个字段
	for i := 0; i < typ.NumField(); i++ {
		// 3.1 拿到反射的config的第i个字段
		f := typ.Field(i)
		// 3.2 拿到赋值了json的字段tag
		if v, ok := f.Tag.Lookup("json"); ok {
			// 3.3 拼接系统环境变量Key
			key := fmt.Sprintf("CONFIG_%s", strings.ReplaceAll(strings.ToUpper(v), "-", "_"))
			// 3.4 从系统中读取环境变量对应的值
			if env, exist := os.LookupEnv(key); exist {
				// 3.5 将值设置到给定名称的字段上
				value.FieldByName(f.Name).Set(reflect.ValueOf(env))
			}
		}
	}
	return &config
}
func main() {
	os.Setenv("CONFIG_SERVER_NAME", "global_server")
	os.Setenv("CONFIG_SERVER_IP", "10.0.0.1")
	os.Setenv("CONFIG_SERVER_URL", "geektutu.com")
	c := readConfig()
	fmt.Printf("%+v", c)
}

到此这篇关于深入了解Golang中reflect反射的使用的文章就介绍到这了,更多相关Go reflect反射内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Go项目与Docker结合实现高效部署深入探究

    Go项目与Docker结合实现高效部署深入探究

    在现代软件开发中,使用Docker部署应用程序已经成为一种标准实践,本文将深入探讨如何将Go项目与Docker结合,实现高效、可靠的部署过程,通过详细的步骤和丰富的示例,你将能够迅速掌握这一流程
    2023-12-12
  • Go高级特性探究之HTTP错误处理详解

    Go高级特性探究之HTTP错误处理详解

    在Web应用程序中,HTTP错误处理是非常重要的,它关系到Web应用程序的稳定性和可靠性,本文介绍如何在Go项目中处理HTTP错误,并提供相应的解决方案和实践经验,希望对Go语言Web应用程序的开发者有所帮助
    2023-06-06
  • golang 实现比特币内核之处理椭圆曲线中的天文数字

    golang 实现比特币内核之处理椭圆曲线中的天文数字

    比特币密码学中涉及到的大数运算超出常规整数范围,需使用golang的big包进行处理,通过使用big.Int类型,能有效避免整数溢出,并保持逻辑正确性,测试展示了在不同质数模下的运算结果,验证了逻辑的准确性,此外,探讨了费马小定理在有限字段除法运算中的应用
    2024-11-11
  • go-zero 组件布隆过滤器使用示例详解

    go-zero 组件布隆过滤器使用示例详解

    这篇文章主要为大家介绍了go-zero组件介绍之布隆过滤器使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • Go语言利用ffmpeg转hls实现简单视频直播

    Go语言利用ffmpeg转hls实现简单视频直播

    这篇文章主要为大家介绍了Go语言利用ffmpeg转hls实现简单视频直播,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • Golang中的int类型和uint类型到底有多大?

    Golang中的int类型和uint类型到底有多大?

    int和uint类型在我们日常开发中经常会用到,但有个疑问就是这两个类型有多大,通过各种尝试最终得到了答案,所以下面这篇文章主要给大家介绍了关于Golang中的int类型和uint类型到底有多大的相关资料,文中通过示例代码介绍的非常详细,需要的朋友可以参考下。
    2017-12-12
  • Go语言框架Beego项目搭建的方法步骤

    Go语言框架Beego项目搭建的方法步骤

    这篇文章主要介绍了Go语言框架Beego项目搭建的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • Gin golang web开发模型绑定实现过程解析

    Gin golang web开发模型绑定实现过程解析

    这篇文章主要介绍了Gin golang web开发模型绑定实现过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-10-10
  • Go整合ElasticSearch的示例代码

    Go整合ElasticSearch的示例代码

    这篇文章主要介绍了Go整合ElasticSearch的相关知识,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2023-07-07
  • Go语言中的并发模式你了解了吗

    Go语言中的并发模式你了解了吗

    工作中查看项目代码,发现会存在使用 GO 语言做并发的时候出现各种各样的异常情况,实际上,出现上述的情况,还是因为我们对于 GO 语言的并发模型和涉及的 GO 语言基础不够扎实,所以本文小编就来带大家深入了解下Go语言中的并发模式吧
    2023-08-08

最新评论