Go语言基础反射示例详解

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

概述

在程序运行期对程序动态的进行访问和修改

reflect godoc: https://golang.org/pkg/reflect/

reflect包有两个数据类型:

Type:数据类型 【reflect.TypeOf():是获取Type的方法】

Value:值的类型【reflect.ValueOf():是获取Value的方法】

语法

一、基本操作

获取变量类型

func TypeOf(i interface{}) Type   //Type是interface{}的别名

例子

reflect.TypeOf(10)  //int
reflect.TypeOf(struct{ age int }{10})  //struct { age int }

获取变量的种类

reflect.TypeOf(struct{ age int }{10}).Kind()  //reflect.Struct
reflect.ValueOf("hello word").Kind()  //reflect.String

获取变量值

func ValueOf(i interface{}) Value   //value是struct {}别名

例子

reflect.ValueOf("hello word")  //hello word
reflect.ValueOf(struct{ age int }{10})   //{10}

二、修改目标对象

修改普通类型

str := "hello word"
reflect.ValueOf(&str).Elem().SetString("张三")

修改结构体

//第一步:ValueOf():传入一个变量的地址,返回是变量的地址     Elem():返回的是变量的原始值
elem:=reflect.ValueOf(&变量名).Elem()
//第二步 FieldByName():传入结构体字段名称   SetString():传入你要修改的变量值
elem.FieldByName("Name").SetString("李四")
//定义一个User结构体
type User struct {
	Name string
	Age  int
}
user := User{Name: "张三", Age: 10}
//Elem() 获取user原始的值
elem := reflect.ValueOf(&user).Elem()
//FieldByName() 通过Name返回具有给定名称的结构字段 通过SetString 修改原始的值
elem.FieldByName("Name").SetString("李四")
elem.FieldByName("Age").SetInt(18)

三、动态调用方法

无参方法

//MethodByName():传方法名,方法名必须大小  Call():方法的形参
reflect.ValueOf(变量名).MethodByName(方法名).Call([]reflect.Value{})
reflect.ValueOf(变量名).MethodByName(方法名).Call(make([]reflect.Value, 0))
type User struct {
	Name string `json:"name" name:"张三"`
	Age  int
}
func (_ User) Say() {
	fmt.Println("user 说话")
}
user := User{Name: "张三", Age: 10}
reflect.ValueOf(&user).MethodByName("Say").Call([]reflect.Value{})
  reflect.ValueOf(user).MethodByName("Say").Call(make([]reflect.Value, 0))

有参方法

reflect.ValueOf(变量名).MethodByName(方法名).Call([]reflect.Value{reflect.ValueOf("该说话了"), reflect.ValueOf(1)})
type User struct {
  Name string `json:"name" name:"张三"`
  Age  int
}
func (_ User) Say() {
  fmt.Println("user 说话")
}
user := User{Name: "张三", Age: 10}
reflect.ValueOf(user).MethodByName("SayContent").Call([]reflect.Value{reflect.ValueOf("该说话了"), reflect.ValueOf(1)})

总结

反射调用struct的方法必须是公有的

反射调用无参方法时必修传 nil 或者 []reflect.Value{}

示例

package main
import (
	"fmt"
	"reflect"
)
func main() {
	//1. 获取变量类型
	fmt.Println("获取变量类型")
	fmt.Println(reflect.TypeOf(10))                          //int
	fmt.Println(reflect.TypeOf(10.0))                        //float64
	fmt.Println(reflect.TypeOf(struct{ age int }{10}))       //struct { age int }
	fmt.Println(reflect.TypeOf(map[string]string{"a": "a"})) //map[string]string
	fmt.Println("")
	//2. 获取变量值
	fmt.Println("获取变量值")
	fmt.Println(reflect.ValueOf("hello word"))                //hello word
	fmt.Println(reflect.ValueOf(struct{ age int }{10}))       //{10}
	fmt.Println(reflect.TypeOf(struct{ age int }{10}).Kind()) //struct
	//类型判断
	if t := reflect.TypeOf(struct{ age int }{10}).Kind(); t == reflect.Struct {
		fmt.Println("是结构体")
	} else {
		fmt.Println("不是结构体")
	}
	//修改目标对象
	str := "hello word"
	//普通变量修改
	reflect.ValueOf(&str).Elem().SetString("张三")
	fmt.Println(str)
	//结构体变量修改
	user := User{Name: "张三", Age: 10}
	//Elem() 获取user原始的值
	elem := reflect.ValueOf(&user).Elem()
	//FieldByName() 通过Name返回具有给定名称的结构字段 通过SetString 修改原始的值
	elem.FieldByName("Name").SetString("李四")
	elem.FieldByName("Age").SetInt(18)
	fmt.Println(user)
	//获取结构体的标签的值
	fmt.Println(reflect.TypeOf(&user).Elem().Field(0).Tag.Get("name"))
	//调用无参方法
	reflect.ValueOf(&user).MethodByName("Say").Call([]reflect.Value{})
	reflect.ValueOf(user).MethodByName("Say").Call(make([]reflect.Value, 0))
	//调用有参方法
	reflect.ValueOf(user).MethodByName("SayContent").Call([]reflect.Value{reflect.ValueOf("该说话了"), reflect.ValueOf(1)})
	//调用本地的方法
	reflect.ValueOf(Hello).Call([]reflect.Value{})
	reflect.ValueOf(Hello).Call(nil)
	fmt.Printf("%#v\n", reflect.TypeOf(user).Field(0))
}
func Hello() {
	fmt.Println("hello")
}
type Person struct {
	Name string
}
type User struct {
	Person        // //反射会将匿名字段作为一个独立字段来处理
	Name   string `json:"name" name:"张三"`
	Age    int
}
func (_ User) Say() {
	fmt.Println("user 说话")
}
func (_ User) SayContent(content string, a int) {
	fmt.Println("user", content, a)
}

以上就是Go语言基础反射示例详解的详细内容,更多关于Go语言反射的资料请关注我们其它相关文章!

(0)

相关推荐

  • Go语言学习笔记之反射用法详解

    本文实例讲述了Go学习笔记之反射用法.分享给大家供大家参考,具体如下: 一.类型(Type) 反射(reflect)让我们能在运行期探知对象的类型信息和内存结构,这从一定程度上弥(mi)补了静态语言在动态行为上的不足.同时,反射还是实现元编程的重要手段. 和 C 数据结构一样,Go 对象头部并没有类型指针,通过其自身是无法在运行期获知任何类型相关信息的.反射操作所需要的全部信息都源自接口变量.接口变量除存储自身类型外,还会保存实际对象的类型数据. func TypeOf(i interface{

  • Go语言基础Json序列化反序列化及文件读写示例详解

    目录 概述 JSON序列化 结构体转JSON map转JSON 切片转JSON JSON反序列化 JSON转map JSON转结构体 JSON转切片 写JSON文件 map写入JSON文件 切片写入JSON文件 结构体写入JSON文件 读JSON文件 解码JSON文件为map 解码JSON文件为切片 解码JSON文件为结构体 示例 概述 JSON(JavaScript Object Notation,JavaScript对象表示法)是一种轻量级的.键值对的数据交换格式.结构由大括号'{}',中括

  • 图文详解go语言反射实现原理

    Go反射的实现和 interface 和 unsafe.Pointer 密切相关.如果对golang的 interface 底层实现还没有理解,可以去看我之前的文章: Go语言interface底层实现 , unsafe.Pointer 会在后续的文章中做介绍. (本文目前使用的Go环境是Go 1.12.9) interface回顾 首先我们简单的回顾一下interface的结构,总体上是: 细分下来分为有函数的 iface 和无函数的 eface (就是 interface{} ); 无函数的

  • Go语言基础单元测试与性能测试示例详解

    目录 概述 单元测试 代码说明如下 问题 注意 性能测试 基本使用 自定义测试时间 概述 测试不是Go语言独有的,其实在很多语言都有测试,例如:Go.Java.Python- 要想成为一名合格的大牛,这是程序员必须具备的一项技能,特别是一些大公司,这是加分的一项,主要有如下优点: 代码可以随时测试,保证代码不会产生错误 写出更加高效的代码 testing文档 Testing_flags文档 单元测试 格式:func TestXXX(t *testing.T) //add.go package c

  • 谈谈Go语言的反射三定律

    简介 Reflection(反射)在计算机中表示 程序能够检查自身结构的能力,尤其是类型.它是元编程的一种形式,也是最容易让人迷惑的一部分. 虽然Go语言没有继承的概念,但为了便于理解,如果一个struct A 实现了 interface B的所有方法时,我们称之为"继承". 类型和接口 反射建立在类型系统之上,因此我们从类型基础知识说起. Go是静态类型语言.每个变量都有且只有一个静态类型,在编译时就已经确定.比如 int.float32.*MyType.[]byte. 如果我们做出

  • Go语言基础闭包的原理分析示例详解

    目录 一. 闭包概述 二. 代码演示 运行结果 代码说明 一. 闭包概述 闭包就是解决局部变量不能被外部访问的一种解决方案 闭包是把函数当作返回值的一种应用 二. 代码演示 总体思想为:在函数内部定义局部变量,把另一个函数当作返回值,局部变量对于返回值函数相当于全部变量,所以多次调用返回值函数局部变量的值跟随变化. // closure.go package main import ( "fmt" "strings" ) func main() { f := clo

  • Go语言基础反射示例详解

    目录 概述 语法 一.基本操作 二.修改目标对象 三.动态调用方法 总结 示例 概述 在程序运行期对程序动态的进行访问和修改 reflect godoc: https://golang.org/pkg/reflect/ reflect包有两个数据类型: Type:数据类型 [reflect.TypeOf():是获取Type的方法] Value:值的类型[reflect.ValueOf():是获取Value的方法] 语法 一.基本操作 获取变量类型 func TypeOf(i interface{

  • Swift进阶教程Mirror反射示例详解

    目录 元类型与.self AnyObject AnyClass Any type(Of:) self self在方法里面的作用 Self Swift Runtime Mirror Mirror的基本用法 Mirror的简单应用-JSON解析 Mirror源码解析 Enum Metadata探索 还原TargetEnumMetadata 还原TargetEnumDescriptor 相对偏移指针 打印枚举中的属性 Struct Metadata探索 获取结构体的属性 swift_getTypeBy

  • C语言指针教程示例详解

    目录 指针 内存 指针类型 指针运算 二级指针 指针数组 指针 指针提供了对地址操作的一种方法,因此,使用指针可使得 C 语言能够更高效地实现对计算机底层硬件的操作.另外,通过指针可以更便捷地操作数组.在一定意义上可以说,指针是 C 语言的精髓. 概念解释就不去搬原定义了,又臭又长不好理解,精炼两点就是: 1.指针是内存中的一个最小单元的编号,也就是地址: 2.平时我们说的指针,通常是指指针变量,用来存储内存地址的变量 也就是说:指针就是地址,口语中指针通常是指针变量 内存 要搞明白指针首先要搞

  • vue实例成员 插值表达式 过滤器基础教程示例详解

    目录 一. 什么是Vue 二.为什么学Vue 三.如何使用Vue 下载安装? 插值表达式 四.vue特点 1.虚拟DOM 2.数据的双向绑定 3.单页面应用 4.数据驱动 五.Vue实例 六.实例成员 - 挂载点 | el - 自定义插值表达式括号| delimiters - 数据 | data - 过滤器 | filters - 方法 | methods - js对象(即字典)补充 - 插值表达式转义 | delimters - 计算属性 | computed - 监听属性 | watch 一

  • Kotlin编程基础数据类型示例详解

    目录 本文总览 1.数值类型 2.布尔型 3.字符串 3.1 字符串字面值 3.2 字符串模板 4.数组 4.1 普通数组 4.2 原⽣类型数组 5.类型检测和类型转换 5.1 智能转换 5.2 is 与 !is 操作符 5.3 转换操作符: as 与 as? 总结 本文总览 上一篇学习了Kotlin基础语法知识,本篇开始会深入探讨一下Kotlin各个基础语法点.首先来熟悉Kotlin的数据类型和类型转换版块. 1.数值类型 在Kotlin中提供了数值类型: 整数类型:Byte,Short,In

  • Go 语言进阶单元测试示例详解

    目录 前言 测试 单元测试 规则 示例 assert 覆盖率 依赖 Mock 基准测试 前言 本文从单元测试实践角度出发,提升对代码质量的意识. 本文内容主要包括:单元测试.Mock测试.基准测试. 测试 测试可以提高代码的质量.减少事故的发生. 测试又分为:回归测试.集成测试.单元测试. 回归测试是指对QA手动回归一些特定场景,可以理解为我们说的手动点点. 集成测试是指对系统功能维度做验证,比如对服务暴露的接口验证,一般是自动化的验证. 单元测试是指在开发阶段,开发者对单独的函数.模块做验证,

  • C及C++ 基础循环示例详解

    目录 正文 手动(通用)方法(迭代方法) 使用循环 循环 While 循环 do-while 循环 正文 在编程中,有时需要多次执行某些操作或(例如)n次.当我们需要重复执行一个语句块时,就会使用循环. 例如:假设我们要打印 10 次“Hello World”.这可以通过两种方式完成,如下所示: 手动(通用)方法(迭代方法) 我们必须手动为 C 编写 print(),为 C++ 语句编写 cout 10 次.假设你必须写 20 次(写 20 条语句肯定会花费更多时间)现在想象你必须写 100 次

  • Go语言的反射机制详解

    反射是语言里面是非常重要的一个特性,我们经常会看见这个词,但是对于反射没有一个很好的理解,主要是因为对于反射的使用场景不太熟悉. 一.理解变量的内在机制 1.类型信息,元信息,是预先定义好的,静态的. 2.值信息,程序进行过程中,动态变化的. 二.反射和空接口 1.空接口相当于一个容器,能接受任何东西. 2.那怎么判断空接口变量存储的是什么类型呢?之前有使用过类型断言,这只是一个比较基础的方法 3.如果想获取存储变量的类型信息和值信息就要使用反射机制,所以反射是什么? 反射就是动态的获取变量类型

  • Java基础篇之反射机制示例详解

    目录 一.什么是反射: 二.反射的原理: 三.反射的优缺点: 四.反射的用途: 五.反射机制常用的类: 六.反射的基本使用: 1.获得Class:主要有三种方法: 2.判断是否为某个类的示例: 3.创建实例:通过反射来生成对象主要有两种方法: 4.通过反射获取构造方法并使用: 5.获取成员变量并调用: 6.获取成员方法并调用: 7.反射main方法: 8.利用反射创建数值: 9.反射方法的其他使用--通过反射运行配置文件内容: 10.反射方法的其他使用--通过反射越过泛型检查: 总结 一.什么是

随机推荐