反射

反射是指程序在运行期对程序本身访问和修改的能力

变量的内在机制

变量包含类型信息和值信息 var arr [10]int arr[0] = 10

类型信息:是静态的元信息,是预先定义好的

值信息:是程序运行过程中动态改变的

反射的使用

reflect包封装了反射相关的方法

获取类型信息:reflect.TypeOf,是静态的

获取值信息:reflect.ValueOf,是动态的

空接口和反射

反射可以在运行时动态获取程序的各种详细信息

反射获取interface类型信息

  1. 反射获取interface类型信息
func main() {
var x = math.Pi
reflectType(x)
} func reflectType(tmp interface{}) {
t := reflect.TypeOf(tmp)
fmt.Println("类型是:", t) // Kind()可以获取具体类型
k := t.Kind()
fmt.Println(k) switch k {
case reflect.Float64:
fmt.Println("Float64类型")
case reflect.String:
fmt.Println("String类型")
} }
  1. 反射获取interface的值信息
func main() {
var x = math.Pi
reflectValue(x)
} func reflectValue(tmp interface{}) {
fmt.Printf("%v: %T\n", tmp, tmp)
v := reflect.ValueOf(tmp)
fmt.Println(v) // 获取到v的具体类型
k := v.Kind()
fmt.Println(k) switch k {
case reflect.Float64:
fmt.Println("float64类型")
}
}
  1. 反射修改值信息
func main() {
var x = math.Pi
// 反射修改值需要传递指针类型,不是float类型
reflectSetValue(&x)
fmt.Println("main: ", x)
} func reflectSetValue(tmp interface{}) {
v := reflect.ValueOf(tmp)
k := v.Kind() // Kind() 获取具体类型
switch k {
case reflect.Float64:
// 反射修改值
v.SetFloat(15)
fmt.Println("tmp is", v.Float())
case reflect.Ptr:
// Elem获取地址指向的值
v.Elem().SetFloat(18)
fmt.Println("tmp is", v.Elem().Float())
fmt.Println(v.Pointer())
}
}

结构体与反射

  1. 查看类型、字段和方法
点击查看代码
type User struct {
Id int
Name string
Age int
}
func (u User) Hello() {
fmt.Println("Hello")
} func main() {
u := User{11, "zhang", 18}
Poni(u)
} func Poni(o interface{}) {
t := reflect.TypeOf(o)
fmt.Println("类型是:", t) // 类型是: main.User
fmt.Println(t.Name()) // User v := reflect.ValueOf(o)
fmt.Println("值是:", v) // 值是: {11 zhang 18} // 获取所有属性
// t.NumField 可以获取字段数量
for i := 0; i < t.NumField(); i++ {
// 获取每个字段
f := t.Field(i)
fmt.Println(f.Name, f.Type) // 获取字段的值信息
val := v.Field(i).Interface() // Interface()获取字段对应的值
fmt.Println(val)
} fmt.Println("==========方法===========")
for i := 0; i < t.NumMethod(); i++ {
m := t.Method(i)
fmt.Println(m.Name, m.Type)
}
}
  1. 查看匿名字段
点击查看代码
type User struct {
Id int
Name string
Age int
}
type Boy struct {
User
Addr string
} func main() {
b := Boy{User{11, "zhang", 18}, "北京市"}
t := reflect.TypeOf(b)
fmt.Println(t) // main.Boy // 匿名:Anonymous
fmt.Printf("%#v\n", t.Field(0))
// 输出:reflect.StructField{Name:"User", PkgPath:"", Type:(*reflect.rtype)(0x3de280), Tag:"", Offset:0x0, Index:[]int{0}, Anonymous:true} // 值信息
fmt.Printf("%#v\n", reflect.ValueOf(b).Field(0))
}
  1. 修改结构体的值
点击查看代码
type User struct {
Id int
Name string
Age int
} func main() {
u := User{11, "zhang", 18}
setValue(&u)
fmt.Println("main:", u)
} // 修改结构体指向的值
func setValue(o interface{}) {
v := reflect.ValueOf(o)
// 获取指针指向的元素
v = v.Elem()
// 获取字段
f := v.FieldByName("Name")
if f.Kind() == reflect.String {
f.SetString("哈哈哈")
}
}
  1. 调用方法
点击查看代码
type User struct {
Id int
Name string
Age int
}
func (User) Hello(name string) {
fmt.Println("hello: ", name)
} func main() {
u := User{11, "lisi", 88}
v := reflect.ValueOf(u)
// 获取方法
m := v.MethodByName("Hello")
// 构建一些参数
args := []reflect.Value{reflect.ValueOf("6666")}
// 没参数的情况下:var args2 []reflect.Value
// 调用方法,需要传入方法的参数
m.Call(args)
}
  1. 获取字段的tag
type Student struct {
Name string `json:"name1" db:"name2"`
} func main() {
s := Student{Name: "lisi"}
v := reflect.ValueOf(&s)
// 注意:如果使用结构体指针,t.Elem()需要获取指针对应的值,如果使用的是s结构体,那么不需要t.Elem(),直接t.Field即可
// 类型
t := v.Type()
// 获取字段
f := t.Elem().Field(0)
fmt.Println(f.Tag.Get("json"))
fmt.Println(f.Tag.Get("db"))
}

golang中的标准库反射的更多相关文章

  1. golang中的标准库数据格式

    数据格式介绍 是系统中数据交互不可缺少的内容 这里主要介绍JSON.XML.MSGPack JSON json是完全独立于语言的文本格式,是k-v的形式 name:zs 应用场景:前后端交互,系统间数 ...

  2. golang中的标准库context

    在 Go http包的Server中,每一个请求在都有一个对应的 goroutine 去处理.请求处理函数通常会启动额外的 goroutine 用来访问后端服务,比如数据库和RPC服务.用来处理一个请 ...

  3. golang中的标准库log

    Go语言内置的log包实现了简单的日志服务.本文介绍了标准库log的基本使用. 使用Logger log包定义了Logger类型,该类型提供了一些格式化输出的方法.本包也提供了一个预定义的" ...

  4. golang中的标准库context解读

    简介 golang 中的创建一个新的 goroutine , 并不会返回像c语言类似的pid,所有我们不能从外部杀死某个goroutine,所有我就得让它自己结束,之前我们用 channel + se ...

  5. golang中的标准库http

    Go语言内置的net/http包十分的优秀,提供了HTTP客户端和服务端的实现. http客户端 基本的HTTP/HTTPS请求 Get.Head.Post和PostForm函数发出HTTP/HTTP ...

  6. golang中的标准库template

    html/template包实现了数据驱动的模板,用于生成可对抗代码注入的安全HTML输出.它提供了和text/template包相同的接口,Go语言中输出HTML的场景都应使用text/templa ...

  7. golang中的标准库IO操作

    参考链接 输入输出的底层原理 终端其实是一个文件,相关实例如下: os.Stdin:标准输入的文件实例,类型为*File os.Stdout:标准输出的文件实例,类型为*File os.Stderr: ...

  8. golang中的标准库time

    时间类型 time.Time类型表示时间.我们可以通过time.Now()函数获取当前的时间对象,然后获取时间对象的年月日时分秒等信息.示例代码如下: func main() { current := ...

  9. golang中的标准库strconv

    strconv 包 strconv包实现了基本数据类型与其字符串表示的转换,主要有以下常用函数: Atoi().Itia().parse系列.format系列.append系列. string与int ...

随机推荐

  1. 分布式NoSQL数据库MongoDB初体验-v5.0.5

    概述 定义 MongoDB官网 https://www.mongodb.com/ 社区版最新版本5.0,其中5.2版本很快也要面世了 MongoDB GitHub源码 https://github.c ...

  2. IDEA控制台中文显示乱码处理

    加入 -Dfile.encoding=UTF-8 以及

  3. JAVA从字符串中提取纯数字

    /** * 从字符串中提取纯数字 * @param str * @return */ public static String getNumeric(String str) { String regE ...

  4. linux 设备文件的操作

    文件:包含数据,具有属性,通过目录中的名字被标识, 可以从文件读数据,可以向文件写数据. 设备也支持文件的操作. 每个设备都被当作一个文件,具有文件名,i-节点号,文件所有者,权限位的集合,最新修改时 ...

  5. 【LeetCode】252. Meeting Rooms 解题报告(C++)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客:http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 排序 日期 题目地址:https://leetcode ...

  6. 【LeetCode】951. Flip Equivalent Binary Trees 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 递归 日期 题目地址:https://leetcod ...

  7. 【LeetCode】394. Decode String 解题报告(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 目录 题目描述 题目大意 解题方法 栈 日期 题目地址:https://leetcode ...

  8. 【LeetCode】888. Fair Candy Swap 公平的糖果棒交换(Python)

    作者: 负雪明烛 id: fuxuemingzhu 个人公众号: 每日算法题 本文关键词:力扣,LeetCode,算法题,算法,Python 目录 题目描述 题目大意 解题方法 代码 刷题心得 关于作 ...

  9. 【LeetCode】623. Add One Row to Tree 解题报告(Python)

    [LeetCode]623. Add One Row to Tree 解题报告(Python) 标签(空格分隔): LeetCode 题目地址:https://leetcode.com/problem ...

  10. python xlwt写Excel表

    1 xlwt第三方库 说明:xlwt是一个用于将数据和格式化信息写入并生成Excel文件的库. 注意:xlwt不支持写xlsx表,打开表文件报错. 官方文档:https://xlwt.readthed ...