golang 通过reflect反射修改值
不是所有的反射值都可以修改。对于一个反射值是否可以修改,可以通过CanSet()进行检查。
要修改值,必须满足:
可以寻址
可寻址的类型:
- 指针指向的具体元素
- slice的元素
- 可寻址的结构体的字段(指向结构体的指针)
- 可寻址的数组的元素(指向数组的指针)
不是结构体没有导出的字段
1.指针指向的具体元素
需要两步:
- 取地址:
v := reflect.ValueOf(&x) - 取得具体值
v=v.Elem()
下面通过一个整型变量的赋值进行说明。
package main
import (
"fmt"
"reflect"
)
func main() {
a := 1
v := reflect.ValueOf(a)
fmt.Println("v Type:", v.Type())
fmt.Println("v CanSet:", v.CanSet())
v = reflect.ValueOf(&a)
fmt.Println("v Type:", v.Type())
fmt.Println("v CanSet:", v.CanSet())
v = v.Elem() // element value
fmt.Println("v Type:", v.Type())
fmt.Println("v CanSet:", v.CanSet())
// set
v.SetInt(2)
fmt.Println("after set, v:", v)
newValue := reflect.ValueOf(3)
v.Set(newValue)
fmt.Println("after set, v:", v)
}
定义一个整型变量,得到反射值,检查是否可以修改。
接着,通过反射获取整型变量地址的反射值,再通过Elem()得到指针指向的具体对象,这样就可以修改值。
输出结果:
v: 1
v Type: int
v CanSet: false
v Type: *int
v CanSet: false
v Type: int
v CanSet: true
after set, v: 2
after set, v: 3
2.slice的元素
需要两步:
- 取切片:
v := reflect.ValueOf(s) - 获取切片的元素
e := v.Index(0)
具体代码如下。
package main
import (
"fmt"
"reflect"
)
func main() {
a := []int{1,1}
v := reflect.ValueOf(a)
fmt.Println("v:", v)
fmt.Println("v Type:", v.Type())
fmt.Println("v CanSet:", v.CanSet())
e := v.Index(0)
fmt.Println("e CanSet:", e.CanSet())
e.SetInt(2)
fmt.Println("after set:", v)
}
定义一个slice,得到反射值,从slice 的反射值中元素,
接着,修改元素的值。
结果输出:
v: [1 1]
v Type: []int
v CanSet: false
e CanSet: true
after set: [2 1]
3.可寻址的结构体的字段
需要三步:
- 取结构体地址
v := reflect.ValueOf(&a) - 获取结构体的具体值:
Elem() - 获取结构体的字段:
FieldByName()
package main
import (
"fmt"
"reflect"
)
type Orange struct {
Size int
}
func main() {
a := Orange{99}
v := reflect.ValueOf(a)
fmt.Println("v:", v)
fmt.Println("v Type:", v.Type())
fmt.Println("v CanSet:", v.CanSet())
v = reflect.ValueOf(&a)
fmt.Println("v:", v)
fmt.Println("v Type:", v.Type())
fmt.Println("v CanSet:", v.CanSet())
//element
v = v.Elem()
size := v.FieldByName("Size")
fmt.Println("size CanSet:", size.CanSet())
size.SetInt(88)
fmt.Println("after set:", v)
}
定义一个结构体变量,首先反射变量,检查是否可以修改值。
接着,使用变量地址进行反射,通过Elem()获取指针指向的具体值。
最后,获取结构体的字段,并修改值。
输出结果
v: {99}
v Type: main.Orange
v CanSet: false
v: &{99}
v Type: *main.Orange
v CanSet: false
size CanSet: true
after set: {88}
4.可寻址的数组的元素
需要三步:
- 取数组地址
v := reflect.ValueOf(&a) - 获取反射对象中的具体值:
Elem() - 通过索引获取元素:
Index(0)
package main
import (
"fmt"
"reflect"
)
func main() {
a := [2]int{1,1}
v := reflect.ValueOf(a)
fmt.Println("v:", v)
fmt.Println("v Type:", v.Type())
fmt.Println("v CanSet:", v.CanSet())
e := v.Index(0)
fmt.Println("e Type:", e.Type())
fmt.Println("e CanSet:", e.CanSet())
v = reflect.ValueOf(&a)
fmt.Println("v:", v)
fmt.Println("v Type:", v.Type())
fmt.Println("v CanSet:", v.CanSet())
// element
v = v.Elem()
e = v.Index(0)
fmt.Println("e Type:", e.Type())
fmt.Println("e CanSet:", e.CanSet())
e.SetInt(3)
fmt.Println("after set:", v)
}
定义一个数组变量,首先反射变量,检查是否可以修改值。
接着,取数组中的元素,检查是否可以修改值。
使用数组的地址进行反射,通过Elem()获取指针指向的具体值。
最后,获取数组中的元素,并修改值。
输出结果
v: [1 1]
v Type: [2]int
v CanSet: false
e Type: int
e CanSet: false
v: &[1 1]
v Type: *[2]int
v CanSet: false
e Type: int
e CanSet: true
after set: [3 1]
golang 通过reflect反射修改值的更多相关文章
- golang:reflect反射
因为之前一直以C++为主要开发语言,所以刚接触go语言中的reflect时感觉很懵逼,因此决定找资料彻底学习一下. 到底反射是什么? https://blog.golang.org/laws-of-r ...
- golang基础--reflect反射
反射的知识点比较晦涩,后期会对此知识点展开深入的分析及示例代码展示 反射可达大提高程序的灵活性,使得inferface{}有更大的发挥余地 反射使用TypeOf和ValueOf函数从接口中获取目标对象 ...
- golang 使用reflect反射结构体
"反射结构体"是指在程序执行时,遍历结构体中的字段以及方法. 1.反射结构体 下面使用一个简单的例子说明如何反射结构体. 定义一个结构体,包括3个字段,以及一个方法. 通过refl ...
- go中的关键字-reflect 反射
1. 什么是反射 Golang提供了一种机制,在编译时不知道类型的情况下,可更新变量.运行时查看值.调用方法以及直接对他们的布局进行操作的机制,称为反射. 2. 反射的使用 2.1 获取变量内部信息 ...
- golang中的反射reflect详解
先重复一遍反射三定律: 1.反射可以将"接口类型变量"转换为"反射类型对象". 2.反射可以将"反射类型对象"转换为"接口类型变量 ...
- Golang 接口与反射知识要点
目录 Golang 接口与反射知识要点 1. 接口类型变量 2. 类型断言 3. 鸭子类型 4. 反射机制 5. reflect 包 TypeOf().ValueOf() Type().Kind() ...
- Golang通脉之反射
什么是反射 官方关于反射定义: Reflection in computing is the ability of a program to examine its own structure, pa ...
- JAVA 构造器, extends[继承], implements[实现], Interface[接口], reflect[反射], clone[克隆], final, static, abstrac
记录一下: 构造器[构造函数]: 在java中如果用户编写类的时候没有提供构造函数,那么编译器会自动提供一个默认构造函数.它会把所有的实例字段设置为默认值:所有的数字变量初始化为0;所有的布尔变量设置 ...
- mybatis批量更新两种方式:1.修改值全部一样 2.修改每条记录值不一样
Mybatis批量更新数据 mybatis批量更新两种方式:1.修改值全部一样 2.修改每条记录值不一样 mybatis批量更新两种方式:1.修改值全部一样 2.修改每条记录值不一样 mybatis批 ...
随机推荐
- ORACLE (BLOB、CLOB、NCLOB、BFILE)
LOB类型 内置的LOB数据类型包括BLOB.CLOB.NCLOB.BFILE(外部存储)的大型化和非结构化数据,如文本.图像.视屏.空间数据存储.BLOB.CLOB.NCLOB类型 4.1 CLOB ...
- PAT Basic 1001 害死人不偿命的(3n+1)猜想 (15 分)
卡拉兹(Callatz)猜想: 对任何一个正整数 n,如果它是偶数,那么把它砍掉一半:如果它是奇数,那么把 ( 砍掉一半.这样一直反复砍下去,最后一定在某一步得到 n=1.卡拉兹在 1950 年的世界 ...
- 多个jar包合并成一个jar包(ant)
https://blog.csdn.net/gzl003csdn/article/details/53539133 多个jar包合并成一个jar 使用Apache的Ant是一个基于Java的生成工具. ...
- 使用cordova调用相机在相机中添加蒙版
变态的需求,要在cordova调起得相机上加入一拍照的轮廓,在cordova的插件中拿不到拍照的方法,起初选用UIImagePickerController的cameraOverlayView属行,结 ...
- 关于ORACLE事务处理的一些笔记
这是2013年在看ORACLE概念手册的时候的一些笔记,现在整理如下(可能跟其他一些文章的内容有重复): 20131012 周六 oracle概念手册中文版 第4章 事务管理 事务具有原子 ...
- spring注解 @profile 以及 注解@Slf4j
@Slf4j 如果不想每次都写private final Logger logger = LoggerFactory.getLogger(XXX.class); 可以用注解@Slf4j 一.在pom ...
- k8spod探测
一.pod存活性探测 pod spec为容器列表中的相应容器定义其专用的探针即可启用存活性探测,目前,k8s的容器支持存活性探测的方法包含:ExecAction.TCPSocketActon和HTTP ...
- TextEdit不能空验证设置
在工具箱中找到dxValidationProvider控件拖拉到界面上,添加代码 ConditionValidationRule notEmptyValidationRule = new Condit ...
- 01-01 Web应用
一 Web应用的组成 接下来我们学习的目的是为了开发一个Web应用程序,而Web应用程序是基于B/S架构的,其中B指的是浏览器,负责向S端发送请求信息,而S端会根据接收到的请求信息返回相应的数据给浏览 ...
- Git 删除本地保存的账号和密码
使用git在本地拉过一次代码时候git会自动将用户名密码保存到本地. 导致想用别的用户名和密码拉代码时没有权限,这时需要删除或者修改git在本地保存的账户名和密码. 具体办法如下: 1.控制面板--& ...