golang基础--reflect反射
反射的知识点比较晦涩,后期会对此知识点展开深入的分析及示例代码展示
反射可达大提高程序的灵活性,使得inferface{}有更大的发挥余地
反射使用TypeOf和ValueOf函数从接口中获取目标对象信息:字段属性,方法信息
package main
import (
"fmt"
"reflect"
)
type User struct { //定义一个结构类型
Id int
Name string
Age int
} func (u User) Hello() { //定义一个结构方法
fmt.Println("Hello world")
} func Info(o interface{}) { //定义一个方法,参数为空接口
t := reflect.TypeOf(o) //获取接收到的接口类型
fmt.Println("Type:", t.Name()) //获取名称 v := reflect.ValueOf(o) //获取接口的字段
fmt.Println("Fields:") //获取结构字段
for i := 0; i < t.NumField(); i++ { //for循环,取出所拥有的字段
f := t.Field(i) //获取值字段
val := v.Field(i).Interface() //获取字段的值
fmt.Printf("%6s:%v=%v\n", f.Name, f.Type, val)
}
//通过接口获取结构的方法
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
fmt.Printf("%6s:%v\n", m.Name, m.Type)
} } func main() {
u := User{1, "OK", 12} //实例化一个结构
Info(u) //调用Info函数 } /*输出
Type: User
Fields:
Id:int=1
Name:string=OK
Age:int=12
Hello:func(main.User)
*/
反射会将匿名字段作为独立字段(匿名字段本质)
package main
import (
"fmt"
"reflect"
) type User struct { //定义一个结构类型
Id int
Name string
Age int
} type Manager struct {
User //嵌入User结构,User就是Manager结构的匿名字段
title string
} func main() {
m := Manager{User: User{1, "mm", 27}, title: "name"} //注意初始化方式
t := reflect.TypeOf(m) //传递结构 fmt.Printf("%#v\n", t.Field(0)) //获取索引为0的字段信息,即User字段信息
fmt.Printf("%#v\n", t.FieldByIndex([]int{0, 0})) //根据索引取出ID的字段信息()
} //{0,0}--User在Manager索引为0,ID在User索引为0 /*output
reflect.StructField{Name:"User", PkgPath:"", Type:(*reflect.rtype)(0x4ac220), Tag:"",
Offset:0x0, Index:[]int{0}, Anonymous:true} "Anonymous:true" 其中包含Anonymous(匿名)字段
*/
想要利用反射修改对象状态,前提是interface.data是settable,即pointer-interface(指针接口)
- 示例1
//这是一个简单的修改对象状态
package main
import (
"fmt"
"reflect"
) func main() {
x := 123 //底层类型是int类型
v := reflect.ValueOf(&x) //传递x的指针
v.Elem().SetInt(999) //通过方法修改x变量的值 fmt.Println(x)
} /*输出
x---> 999
*/
- 示例2
//通过反射修改结构字段
package main
import (
"fmt"
"reflect"
) type User struct {
Name string
ID int
Age int
} func main() {
u := User{"MAOZI", 1, 22}
Set(&u)
fmt.Println(u) } func Set(o interface{}) {
v := reflect.ValueOf(o) if v.Kind() != reflect.Ptr && !v.Elem().CanSet() { //判断是否为反射typestring,且可以被修改
fmt.Println("fuck")
return
} else { //如果条件都满足
v = v.Elem()
} f := v.FieldByName("Name") //通过名字段名找字段
if !f.IsValid() { //IsValid方法判断是否找了字段
fmt.Println("invalid")
return
}
if f.Kind() == reflect.String {
f.SetString("momo")
} } /*输出
{momo 1 22}
*/
通过反射可以"动态"调用方法
//通过反射动态调用结构方法
package main
import (
"fmt"
"reflect"
) type User struct {
Name string
ID int
Age int
} func (u User) Hello(name string) {
fmt.Println("Hello", name, ",my name is", u.Name) }
func main() {
u := User{"Golang", 1, 22}
v := reflect.ValueOf(u)
mv := v.MethodByName("Hello") //反射:通过名字找结构字段信息 args := []reflect.Value{reflect.ValueOf("Python")}
mv.Call(args) } /*输出
Hello Python ,my name is Golang
*/
golang基础--reflect反射的更多相关文章
- golang:reflect反射
因为之前一直以C++为主要开发语言,所以刚接触go语言中的reflect时感觉很懵逼,因此决定找资料彻底学习一下. 到底反射是什么? https://blog.golang.org/laws-of-r ...
- golang 使用reflect反射结构体
"反射结构体"是指在程序执行时,遍历结构体中的字段以及方法. 1.反射结构体 下面使用一个简单的例子说明如何反射结构体. 定义一个结构体,包括3个字段,以及一个方法. 通过refl ...
- golang 通过reflect反射修改值
不是所有的反射值都可以修改.对于一个反射值是否可以修改,可以通过CanSet()进行检查. 要修改值,必须满足: 可以寻址 可寻址的类型: 指针指向的具体元素 slice的元素 可寻址的结构体的字段( ...
- golang中的反射reflect详解
先重复一遍反射三定律: 1.反射可以将"接口类型变量"转换为"反射类型对象". 2.反射可以将"反射类型对象"转换为"接口类型变量 ...
- Go语言基础之反射
Go语言基础之反射 本文介绍了Go语言反射的意义和基本使用. 变量的内在机制 Go语言中的变量是分为两部分的: 类型信息:预先定义好的元信息. 值信息:程序运行过程中可动态变化的. 反射介绍 反射是指 ...
- Golang 接口与反射知识要点
目录 Golang 接口与反射知识要点 1. 接口类型变量 2. 类型断言 3. 鸭子类型 4. 反射机制 5. reflect 包 TypeOf().ValueOf() Type().Kind() ...
- GO学习-(17) Go语言基础之反射
Go语言基础之反射 本文介绍了Go语言反射的意义和基本使用. 变量的内在机制 Go语言中的变量是分为两部分的: 类型信息:预先定义好的元信息. 值信息:程序运行过程中可动态变化的. 反射介绍 反射是指 ...
- Golang 基础之基础语法梳理 (三)
大家好,今天将梳理出的 Go语言基础语法内容,分享给大家. 请多多指教,谢谢. 本次<Go语言基础语法内容>共分为三个章节,本文为第三章节 Golang 基础之基础语法梳理 (一) Gol ...
- 黑马程序员:Java基础总结----反射
黑马程序员:Java基础总结 反射 ASP.Net+Android+IO开发 . .Net培训 .期待与您交流! 反射 反射的基石:Class类 Class类代表Java类,它的各个实例对象又分别 ...
随机推荐
- JSONP的原理与实现(基于jQuery)
为什么会有JSONP?因为我们使用AJAX,使用AJAX可能就会遇到跨域的需求,如何解决呢,对,就是JSONP. 这里注意下JSON和JSONP不是一类,虽然他们只是一个字母只差,但是实际差别很大.这 ...
- 在Sublime中集成Team Foundation Server (TFS),实现版本管理
Sublime是一款具有代码高亮.语法提示.自动完成且反应快速的编辑器软件,由于它开发的技术架构.丰富的插件,和轻盈而快速的编程响应,Sublime广受程序员的爱好.在C, C++, Javascri ...
- JQuery fullcalender文档
转载: http://blog.csdn.net/lgg2011. 使用方式, 引入相关js, css后, $(‘#div_name’).fullCalendar({//options}); 接受的 ...
- C#使用Linq对DataGridView进行模糊查找
针对DataGridView中已进行过数据绑定,即已向DataGridView中添加了一些数据,可以结合Linq查询,并让匹配查询的行高亮显示,如下图: 具体实现如下: [csharp] ...
- 在微信开发中如果WeixinJSBridge.call('closeWindow');关闭窗口无效!
原因是,成功后页面跳转到普通页面.必须在前面加上 parent.WeixinJSBridge.call('closeWindow'); 这样才行.如果是使用了iframe页面,这样也可以关闭网页,回到 ...
- sqlServer数据库常用连接字符串
sqlServer 数据库常用连接字符串 用户名和密码验证的方式去连接到数据库服务器 <add name="conStr" connectionString=" ...
- Day 8 集合与文件的操作
一.创建集合两种方式. 二.添加元素的方式(add.update"属于迭代添加") 一.集合# 1. 集合是无序的,不能重复的.# 2.集合内元素必须是可哈希的.# 3.集合不能更 ...
- 删除 iptables nat 规则
原文:https://www.cnblogs.com/hixiaowei/p/8954161.html 删除FORWARD 规则: iptables -nL FORWARD --line-number ...
- BZOJ 1003--[ZJOI2006]物流运输(最短路)
1003: [ZJOI2006]物流运输 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 10034 Solved: 4403 Description ...
- hot code loading in nodejs
Hot Code Loading in Node.js Node.js Web应用代码热更新的另类思路 Reading through Fever today, this post by Jack M ...