go反射----2值
声明:文章内容取自雨痕老师《Go语言学习笔记》
和Type获取类型信息不同,Value专注于对象实例数据读写。
在前面章节曾提到过,接口变量会复制对象,且是unaddressable的,所以要想修改目标对象,就必须使用指针。
package main
import (
"fmt"
"reflect"
)
func main() {
a := 100
va, vp := reflect.ValueOf(a), reflect.ValueOf(&a).Elem()
fmt.Println(va.CanAddr(), va.CanSet())
fmt.Println(vp.CanAddr(), vp.CanSet())
}
输出:
false false
true true
就算传入指针,一样需要通过Elem获取目标对象。因为被接口存储的指针本身是不能寻址和进行设置操作的。
注意,不能对非导出字段直接进行设置操作,无论是当前包还是外包。
```golang
package main
import (
"fmt"
"reflect"
"unsafe"
)
type User struct {
Name string
code int
}
func main() {
p := new(User)
v := reflect.ValueOf(p).Elem()
name := v.FieldByName("Name")
code := v.FieldByName("code")
fmt.Printf("name:canaddr = %v,canset = %v\n", name.CanAddr(), name.CanSet())
fmt.Printf("code:canaddr = %v,canset = %v\n", code.CanAddr(), code.CanSet())
if name.CanSet() {
name.SetString("Tom")
}
if code.CanAddr() {
(int)(unsafe.Pointer(code.UnsafeAddr())) = 100
}
fmt.Printf("%+v\n", *p)
}
输出:
name:canaddr = true,canset = true
code:canaddr = true,canset = false
{Name:Tom code:100}
<hr>
Value.Pointer和Value.Int等方法类似,将Value.data存储的数据转换为指针,目标必须是指针类型。而UnsafeAddr返回任何CanAddr Value.data地址(相当于&取地址操作),比如Elem后的Value,以及字段成员地址。
以结构体里的指针类型字段为例,Pointer返回该字段所保存的地址,而UnsafeAddr返回该字段自身的地址(结构对象地址+偏移量)
<hr>
可通过Interface方法进行类型推断和转换。
```golang
package main
import (
"fmt"
"reflect"
)
type user struct {
Name string
Age int
}
func main() {
u := user{
"雨痕",
60, //如果最后一个字段不和}相连,则必须加上,
}
v := reflect.ValueOf(&u)
if !v.CanInterface() {
fmt.Println("CanInterfae:fail.")
return
}
p, ok := v.Interface().(*user)
if !ok {
fmt.Println("Interface:fail.")
return
}
p.Age++
fmt.Printf("%+v\n", u)
}
输出:
{Name:雨痕 Age:61}
也可直接使用Value.Int、Bool等方法进行类型转换,但失败时会引发panic,且不支持ok-idiom。
复合类型对象设置示例:
```golang
package main
import (
"fmt"
"reflect"
)
func main() {
c := make(chan int, 4)
v := reflect.ValueOf(c)
if v.TrySend(reflect.ValueOf(100)) {
fmt.Println(v.TryRecv())
}
}
输出:
100 true
接口有两种nil状态,这一直是个潜在麻烦。解决方法是用IsNil判断值是否为nil。
```golang
package main
import (
"fmt"
"reflect"
)
func main() {
var a interface{} = nil
var b interface{} = (*int)(nil)
fmt.Println(a == nil)
fmt.Println(b == nil, reflect.ValueOf(b).IsNil())
}
输出:
true
false true
也可用unsafe转换后直接判断iface.data是否为零值。
package main
import (
"fmt"
"unsafe"
)
func main() {
var b interface{} = (*int)(nil)
iface := (*[2]uintptr)(unsafe.Pointer(&b))
fmt.Println(iface, iface[1] == 0)
}
输出:
&[4785664 0] true
让人很无奈的是,Value里的某些方法并未实现ok-idom或返回error,所以得自行判断返回的是否为Zero Value。
package main
import (
"fmt"
"reflect"
)
func main() {
v := reflect.ValueOf(struct{ name string }{})
fmt.Println(v.FieldByName("name").IsValid())
fmt.Println(v.FieldByName("xxx").IsValid())
}
输出:
true
false
go反射----2值的更多相关文章
- 【记录】【java】反射设值取值
1.设值 /** * 根据属性名设置属性值 * * @param fieldName * @param object * @return */ public boolean setFieldValue ...
- Final修饰的字段是否可以通过反射设置值
案发现场 经常听说final修饰的字段是常量不能改变的他的值,但是以外发现 Integer.java源码中的字段“value”是final,但是可以通过反射改变他的值. public final cl ...
- Go语言反射之值反射
1 概述 反射不仅可以获取值的类型信息,还可操作变量的值.使用 reflect.Value 类型操作变量的值. 2 值反射对象 reflect.ValueOf() 方法可以获取一个值的反射对象,之后可 ...
- 要使用myConfig.properties配置文件作为实体类的映射文件的话,格式要用=,最关键的要和实例类中通过反射获取值的KEY要一样,不样会反射取不到值
ABC=https://fsdfsdf.iy.comABCId=L2345345ZhP345ABCKey=sfdf4234f234dhE6Ut0aABCName=Gassd010 上面是myConfi ...
- 用反射的形式将一个对象属性值赋值给另一个对象,省略点get/set方法的冗余代码
1.本例使用的是idea 首先需要在idea中安装lombok插件,省略getter和setter方法的书写 在maven项目中加入lombok依赖 <dependency> <gr ...
- Go part 7 反射,反射类型对象,反射值对象
反射 反射是指在程序运行期间对程序本身进行访问和修改的能力,(程序在编译时,变量被转换为内存地址,变量名不会被编译器写入到可执行部分,在运行程序时,程序无法获取自身的信息) 支持反射的语言可以在程序编 ...
- 通过JAVA反射,调用未知类的类方法
下面是一个比较简单的通过JAVA的反射机制调用已知方法的例子 package com.togeek.mvntest; import java.lang.reflect.InvocationTarget ...
- struts2 笔记01 登录、常用配置参数、Action访问Servlet API 和设置Action中对象的值、命名空间和乱码处理、Action中包含多个方法如何调用
Struts2登录 1. 需要注意:Struts2需要运行在JRE1.5及以上版本 2. 在web.xml配置文件中,配置StrutsPrepareAndExecuteFilter或FilterDis ...
- 反射获取类中的属性和set属性
package framework.base; import java.beans.IntrospectionException; import java.beans.PropertyDescript ...
随机推荐
- Maven 使用 二——nexus
上篇博客介绍了创建maven项目的两种方式,当中一种是使用命令行的方式来创建,这种情况非常少,一般我们都有IDE开发环境.所以接下来,我们还是在一个详细的IDE中来说,我使用的是Eclipse. 一. ...
- druid.io使用技术简介: Hyperloglog
druid.io 使用Hyperloglog 估计基数 参照如下连接 http://blog.codinglabs.org/articles/algorithms-for-cardinality-es ...
- g++ 链接静态库命令应该放在最后
昨天编译去年写的FloorServer,居然一堆错误: chu@chu-laptop:/media/E/work/github/FloorServer/FloorServer$ makeg++ -g ...
- Directive Controller And Link Timing In AngularJS
I've talked about the timing of directives in AngularJS a few times before. But, it's a rather compl ...
- Netty源码细节IO线程(EventLoop)(转)
原文:http://budairenqin.iteye.com/blog/2215896 源码来自Netty5.x版本, 本系列文章不打算从架构的角度去讨论netty, 只想从源码细节展开, 又不想通 ...
- Centos 7 搭建蓝鲸V4.1.16社区版
第一次搭建蓝鲸平台,参考了蓝鲸社区的官方搭建文档. 友情链接:蓝鲸智云社区版V4.1.16用户手册 搭建时遇到了不少的坑,这里做一个详细的安装梳理 主机硬件要求 官方的推荐如下: 在本地用VMware ...
- qml自学笔记------自己写相似于劲舞团的按键小游戏(中)
接上篇<qml自学笔记------自己写类似于劲舞团的按键小游戏(上)> 第三部分DisplayPart.qml 代码的其它部分都是渣,就这里花了点时间,整个小游戏就靠这个文件. 首先,屏 ...
- LeetCode——Anagrams
Given an array of strings, return all groups of strings that are anagrams. Note: All inputs will be ...
- vue 结合localStorage 来双向绑定数据
结合localStorage 来双向绑定数据(超级神奇) localStorage.js: const STORAGE_KEY = 'todos_vuejs' export default { fet ...
- Silverlight实例教程 - Validation客户端同步数据验证(转载)
摘要:在Silverlight 4中,Silverlight Validation有相对的改进,本篇将介绍Silverlight 4中新加入的验证机制功能,IDataErrorInfo客户端同步验证机 ...