参考自liwenzhou
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.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)
}
}