文档章节

golang reflect

别人说我名字很长
 别人说我名字很长
发布于 2015/10/05 09:52
字数 1199
阅读 714
收藏 3

reflect包实现了运行时反射,允许程序操作任意类型的对象。典型用法是用静态类型interface{}保存一个值,通过调用TypeOf获取其动态类型信息,该函数返回一个Type类型值。调用ValueOf函数返回一个Value类型值,该值代表运行时的数据。Zero接受一个Type类型参数并返回一个代表该类型零值的Value类型值

type

package main

import (
	"reflect"

	"fmt"
)

type lx interface {
	SayHi()
}

type User struct {
	Name string
	Age  int64
	Sex  string
}

func (u *User) SayHi() {
	fmt.Println("hello world")
}

func main() {
	user := User{"张三", 25, "男"}
	FillStruct(user)
}

func FillStruct(obj interface{}) {
	t := reflect.TypeOf(obj)       //反射出一个interface{}的类型
	fmt.Println(t.Name())          //类型名
	fmt.Println(t.Kind().String()) //Type类型表示的具体分类
	fmt.Println(t.PkgPath())       //反射对象所在的短包名
	fmt.Println(t.String())        //包名.类型名
	fmt.Println(t.Size())          //要保存一个该类型要多少个字节
	fmt.Println(t.Align())         //返回当从内存中申请一个该类型值时,会对齐的字节数
	fmt.Println(t.FieldAlign())    //返回当该类型作为结构体的字段时,会对齐的字节数

	var u User
	fmt.Println(t.AssignableTo(reflect.TypeOf(u)))  // 如果该类型的值可以直接赋值给u代表的类型,返回真
	fmt.Println(t.ConvertibleTo(reflect.TypeOf(u))) // 如该类型的值可以转换为u代表的类型,返回真

	fmt.Println(t.NumField())             // 返回struct类型的字段数(匿名字段算作一个字段),如非结构体类型将panic
	fmt.Println(t.Field(0).Name)          // 返回struct类型的第i个字段的类型,如非结构体或者i不在[0, NumField())内将会panic
	fmt.Println(t.FieldByName("Age"))     // 返回该类型名为name的字段(会查找匿名字段及其子字段),布尔值说明是否找到,如非结构体将panic
	fmt.Println(t.FieldByIndex([]int{0})) // 返回索引序列指定的嵌套字段的类型,等价于用索引中每个值链式调用本方法,如非结构体将会panic
}



Value

package main

import (
	"reflect"

	"fmt"
)

type User struct {
	Name  string
	Age   int
	Sex   bool
	Phone *string
	Qian  float64
	Atest uint
	Group interface{}
	Btest interface{}
}

func (u *User) Hello() {
	fmt.Println("hello world 你好世界")
}

func main() {

	a := "hello world 你好世界"
	user := &User{"张三", 25, true, &a, 88.8, 9, 99, nil}

	var obj interface{} = user
	v := reflect.ValueOf(obj)

	method := v.MethodByName("Hello") //返回v的名为Hello的方法
	method.Call([]reflect.Value{})    //执行反射的方法

	fmt.Println(v.IsValid()) //返回v是否持有值,如果v是value零值会返回假,此时v除了IsValid String Kind之外的方法都会导致panic
	fmt.Println(v.Kind())    //返回v持有值的分类,如果v是value零值,返回值为invalid
	fmt.Println(v.Type())    //返回v持有值的类型Type表示

	v = v.Elem() //返回持有的接口的值,或者指针的值,如果不是interface{}或指针会panic,实际上是从 *User到User
	var u User
	fmt.Println(v.Convert(reflect.TypeOf(u)).FieldByName("Name")) //转换为其他类型的值,如果无法使用标准Go转换规则来转换,那么panic

	fmt.Println(v.FieldByName("Name").CanSet())   //是否可以设置Name的值
	v.FieldByName("Name").SetString("把Name值修改一下") //设置v的持有值,如果v的kind不是string或者v.Canset()返回假,会panic
	v.FieldByName("Name").Set(reflect.ValueOf(a)) //将v的持有值修改为a的反射值,如果Canset返回假,会panic

	fmt.Println(v.FieldByName("Group").Elem())     //返回持有的接口的值,或者指针的值,如果不是interface{}或指针会panic
	fmt.Println(v.FieldByName("Phone").Elem())     //或者指针的值
	fmt.Println(v.FieldByName("Name").Interface()) //把Name当做interface{}值

	fmt.Println(v.FieldByName("Name").String()) //返回v持有的值的字符串表示,如果v的值不是string也不会panic
	fmt.Println(v.FieldByName("Sex").Bool())    //返回持有的布尔值,如果v的kind不是bool会panic
	fmt.Println(v.FieldByName("Age").Int())     //返回持有的int64,如果v的kind不是int int8-int64会panic

	var x int64
	fmt.Println(v.FieldByName("Age").OverflowInt(x)) //如果v持有值的类型不能无一出的表示x,会返回真,如果v的kind不是int int8-int64会panic
	fmt.Println(v.FieldByName("Atest").Uint())       //返回v持有的无符号整数,如果v的kind不是uint uintptr uint8 uint16 uint32 uint64会panic

	var x2 uint64
	fmt.Println(v.FieldByName("Atest").OverflowUint(x2)) //如果v持有的值的类型不能无溢出的表示x2,会返回真,如果v的kind不是uint uintptr uint8 uint16 uint32 uint64会panic
	fmt.Println(v.FieldByName("Qian").Float())           //返回v持有的浮点数float64,如果v的kind不是float32 float64会panic

	var x3 float64
	fmt.Println(v.FieldByName("Qian").OverflowFloat(x3)) //如果v持有值的类型不能无溢出的表示x3,会返回真,如果v的kind不是float32 float64会panic
	fmt.Println(v.FieldByName("Btest").IsNil())          //如果v持有值是否为nil,如果v的值不是通道 函数 接口 映射 指针 切片之一会panic

	fmt.Println(v.NumField())             //返回v持有的结构体类型值的字段数,如果v的kind不是struct会panic
	fmt.Println(v.Field(0))               //返回结构体的第i个字段,如果v的kind不是struct或i出界会panic
	fmt.Println(v.FieldByIndex([]int{0})) //和上面一样,没明白有啥用

}




© 著作权归作者所有

共有 人打赏支持
上一篇: golang html/template
下一篇: golang map to struct
别人说我名字很长
粉丝 58
博文 259
码字总数 112570
作品 0
济南
程序员
私信 提问
加载中

评论(2)

别人说我名字很长
别人说我名字很长

引用来自“3xxx”的评论

map[string]interface{}怎么转成map[]string呢

map[]string 没有这种类型
3xxx
3xxx
map[string]interface{}怎么转成map[]string呢
golang 随笔

golang reflect go blog随笔 最近看go blog, 发现go升级到1.7了,最大的改进是编译的二进制文件缩小了近30%. 那么这30%是怎么来的呢,什么特征使其压缩了文件大小: ssa (Static Single A...

panda1986_meng
2016/09/07
19
0
Golang的反射reflect深入理解和示例

作者:豆瓣奶茶 链接:https://www.jianshu.com/p/b46b1ccd2757 來源:简书 编程语言中反射的概念 在计算机科学领域,反射是指一类应用,它们能够自描述和自控制。也就是说,这类应用通过采用...

Golang语言社区
2018/10/15
0
0
golang实现web中间件的一些思考

最近陆续看了golang的Martini框架,也试用了,这个山寨自node.js的Express框架和最新的koa框架的golang框架, 同样具有低耦合的特点,不过还是担忧其性能,因为核心采用了reflect反射技术。 ...

yzq1979
2014/04/15
0
0
Go 语言反射和范型在 API 服务中的应用

为何需要使用 reflect 获取:减少重复代码 1. API 接口中抽取参数的逻辑大量重复   API 接口自然是要获取传过来的数据,不同接口要获取的数据自然也不一样,如果不做特殊处理,必然是每个接...

blackpiglet
2018/04/27
0
0
golang Reflect包

Reflect包 Reflect 反射包有2个重要的类型,分别通过和返回。分别在源码包里的包中的和 Type TypeOf() 返回一个接口类型,源码中 有一个结构体 实现了接口的所有方法。源码: TypeOf会返回一...

johnL
2018/03/05
6
0

没有更多内容

加载失败,请刷新页面

加载更多

Java单例模式学习记录

在项目开发中经常能遇见的设计模式就是单例模式了,而实现的方式最常见的有两种:饿汉和饱汉(懒汉)。由于日常接触较多而研究的不够深入,导致面试的时候被询问到后有点没底,这里记录一下学习...

JerryLin123
昨天
3
0
VSCODE 无法调试

VSCODE 无法调试 可以运行 可能的原因: GCC 的参数忘了加 -g

shzwork
昨天
4
0
理解去中心化 稳定币 DAI

随着摩根大通推出JPM Coin 稳定币,可以预见稳定币将成为区块链落地的一大助推器。 坦白来讲,对于一个程序员的我来讲(不懂一点专业经济和金融),理解DAI的机制,真的有一点复杂。耐心看完...

Tiny熊
昨天
4
0
5.线程实现

用于线程实现的Python模块 Python线程有时称为轻量级进程,因为线程比进程占用的内存少得多。 线程允许一次执行多个任务。 在Python中,以下两个模块在一个程序中实现线程 - _thread 模块 th...

Eappo_Geng
昨天
6
0
ServiceLoader

创建一个接口文件在resources资源目录下创建META-INF/services文件夹在services文件夹中创建文件,以接口全名命名创建接口实现类 内容me.zzp.ar.d.PostgreSQLDialectme.zzp.ar.d.Hype...

Cobbage
昨天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部