[Go关于反射] reflect包
Posted issue是fw
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[Go关于反射] reflect包相关的知识,希望对你有一定的参考价值。
ORM库要用到, 记录一下.
文章目录
reflect.TypeOf() 获取对象类型
在Go语言中,使用reflect.TypeOf()
函数可以获得任意值的类型对象(reflect.Type
)
程序通过类型对象可以访问任意值的类型信息。
func reflectType(x interface)
v := reflect.TypeOf( x )
fmt.Printf("type: %v\\n",v )
func main()
var a float32 = 3.14
reflectType( a ) // type: float32
var b int64 = 100
reflectType( b ) // type: int64
type name和type kind
type tk int64
var(
a *float32 //指针
b tk //自定义类型
by byte //类型别名
user = User "cl",20
)
type User struct
Name string
Age int
func reflectType(x interface )
temp := reflect.TypeOf( x )
fmt.Printf("type: %v kind: %v\\n", temp.Name(),temp.Kind() )
func main()
reflectType( a )
reflectType( b )
reflectType( by ) // byte是官方定义的类型,所以输出和自定义的不一样
reflectType( user )
输出为
type: kind: ptr
type: tk kind: int64
type: uint8 kind: uint8
type: User kind: struct
可以发现Kind
总是比Type
更接近底层, 而Type
则是输出自定义类型的名字而不是底层
Go语言的反射中像数组、切片、Map、指针等类型的变量,它们的.Name()
都是返回空。
reflect.ValueOf()
reflect.ValueOf()
返回reflect.Value
类型,其中包含了原始值的值信息。reflect.Value与原始值之间可以互相转换。
func reflectValue(x interface)
v := reflect.ValueOf(x)
k := v.Kind()
switch k
case reflect.Int64:
// v.Int()从反射中获取整型的原始值,然后通过int64()强制类型转换
fmt.Printf("type is int64, value is %d\\n", int64(v.Int()))
case reflect.Float32:
// v.Float()从反射中获取浮点型的原始值,然后通过float32()强制类型转换
fmt.Printf("type is float32, value is %f\\n", float32(v.Float()))
case reflect.Float64:
// v.Float()从反射中获取浮点型的原始值,然后通过float64()强制类型转换
fmt.Printf("type is float64, value is %f\\n", float64(v.Float()))
func main()
var a float32 = 3.14
var b int64 = 100
reflectValue(a) // type is float32, value is 3.140000
reflectValue(b) // type is int64, value is 100
reflect.Value.Elem()获取指针对应的值并修改
使用反射修改变量值
func reflectSetValue1(x interface)
v := reflect.ValueOf(x)
if v.Kind() == reflect.Int64
v.SetInt(200) //修改的是副本,reflect包会引发panic
func reflectSetValue2(x interface)
v := reflect.ValueOf(x)
//fmt.Println( v.Kind() )
//fmt.Println( v.Elem().Kind() )
// 反射中使用 Elem()方法获取指针对应的值
if v.Elem().Kind() == reflect.Int64
v.Elem().SetInt(200)
func main()
var a int64 = 100
// reflectSetValue1(a) //panic: reflect: reflect.Value.SetInt using unaddressable value
reflectSetValue2(&a)
fmt.Println(a)
reflect.Indirect()于reflect.elem()区别
// Indirect returns the value that v points to.
// If v is a nil pointer, Indirect returns a zero Value.
// If v is not a pointer, Indirect returns v.
func Indirect(v Value) Value
Indirect
返回
v
v
v指向的值
若 v v v是空指针, 返回 0 0 0值
若 v v v不是指针,返回 v v v本身
大概意思就是把指针值转为原始值
比如下面,传入一个指针的interface
转化为原始值reflect.Type
的做法
type User struct
name string
age int
addr string
func main()
uu := User"tom", 27, "beijing"
u := &uu
v := reflect.ValueOf(u)
t := reflect.TypeOf(u)
fmt.Println("TypeOf=", t)
t1 := reflect.Indirect(v).Type()
fmt.Println("t1=", t1)
如果reflect.Value
是指针,则v.Elem()
等效于reflect.Indirect(v)
。
如果不是指针,则它们不是等效的:
如果该值是接口,reflect.Indirect(v)
则将返回相同的值,而v.Elem()
将返回所包含的动态值。
如果该值是其他值,则将感到v.Elem()引发的panic
。
该reflect.Indirect
助手用于需要接受特定类型或指向该类型的指针的情况。
结构体反射
任意值通过reflect.TypeOf()
获得反射对象信息后,如果它的类型是结构体
可以通过反射值对象(reflect.Type
)的NumField()
和Field()
方法获得结构体成员的详细信息。
type student struct
Name string `json:"name"`
Score int `json:"score"`
func main()
stu1 := student
Name: "小王子",
Score: 90,
t := reflect.TypeOf(stu1)
fmt.Println(t.Name(), t.Kind()) // student struct
// 通过for循环遍历结构体的所有字段信息
for i := 0; i < t.NumField(); i++
field := t.Field(i)
fmt.Printf("name:%s index:%d type:%v json tag:%v\\n", field.Name, field.Index, field.Type, field.Tag.Get("json"))
// 通过字段名获取指定结构体字段信息
if scoreField, ok := t.FieldByName("Score"); ok
fmt.Printf("name:%s index:%d type:%v json tag:%v\\n", scoreField.Name, scoreField.Index, scoreField.Type, scoreField.Tag.Get("json"))
遍历结构体包含的所有方法并调用
// 给student添加两个方法 Study和Sleep(注意首字母大写)
func (s student) Study() string
msg := "好好学习,天天向上。"
fmt.Println(msg)
return msg
func (s student) Sleep() string
msg := "好好睡觉,快快长大。"
fmt.Println(msg)
return msg
func printMethod(x interface)
t := reflect.TypeOf(x)
v := reflect.ValueOf(x)
fmt.Println(t.NumMethod())
for i := 0; i < v.NumMethod(); i++
methodType := v.Method(i).Type()
fmt.Printf("method name:%s\\n", t.Method(i).Name)
fmt.Printf("method:%s\\n", methodType)
// 通过反射调用方法传递的参数必须是 []reflect.Value 类型
var args = []reflect.Value
v.Method(i).Call(args)
以上是关于[Go关于反射] reflect包的主要内容,如果未能解决你的问题,请参考以下文章