反射

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

变量的内在机制

变量包含类型信息和值信息 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. 【LeetCode】1001. Grid Illumination 解题报告(C++)

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

  2. 【LeetCode】392. Is Subsequence 解题报告(Python)

    [LeetCode]392. Is Subsequence 解题报告(Python) 标签: LeetCode 题目地址:https://leetcode.com/problems/is-subseq ...

  3. [LeetCode]485. Max Consecutive Ones 找到最大的连续的1的个数

    题目描述 输入只有0和1的数组(长度为正整数,且<10000),找到最大的连续1的个数 比如[1,1,0,1,1,1],输出3 思路 遍历数组,统计当前连续个数curCount和最大连续值max ...

  4. 15 - Vue3 UI Framework - 完工部署

    项目官网也基本完成了,接下来我们再讲一下如何将项目官网部署到 GitHub Pages 上 返回阅读列表点击 这里 项目配置 常见的模式有三种,即 History 模式 Hash 模式 Memory ...

  5. Spring Boot + MyBatis + MySQL 实现读写分离

    读写分离要做的事情就是对于一条SQL该选择哪个数据库去执行,至于谁来做选择数据库这件事儿,无非两个,要么中间件帮我们做,要么程序自己做. 读写分离有两种实现方式: 第一种是依靠中间件(比如:MyCat ...

  6. HDFS源码解析:教你用HDFS客户端写数据

    摘要:终于开始了这个很感兴趣但是一直觉得困难重重的源码解析工作,也算是一个好的开端. 本文分享自华为云社区<hdfs源码解析之客户端写数据>,作者: dayu_dls. 在我们客户端写数据 ...

  7. [git]初始化项目文件到git分支

    将本地和远程仓库关联并push本地项目 1.VCS -> import into Version Control  ->  Create Git Repository 选择项目文件   2 ...

  8. 编写Java程序,定义士兵类(Soldiers)并初始化5个士兵对象。

    返回本章节 返回作业目录 需求说明: 创建士兵类(Soldiers),定义有一个String类型参数name,代表士兵的姓名,两个int类型变量x和y,分别表示士兵所在的坐标位置,x代表横坐标,y代表 ...

  9. 编写Java程序_银行终端服务系统

    目录 一.General description 总体概述 二.About the Project 项目介绍 三.Soft function 软件功能 四.UI Model Use Case Diag ...

  10. Hadoop编译打包记录

    Hadoop编译打包,基于2.7.2版本的源码. # 打包过程中需要使用到的工具 java -version mvn -version ant -version type protoc type cm ...