Go语言中反射(reflect)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
package main

import (
"fmt"
"reflect"
)

//go语言中变量分为两部分
// 类型信息:预先定义好元信息
// 值信息:程序运行过程中可动态变化

//reflect包
//reflect.TypeOf 获取任意值的类型对象(reflect.Type)

//获取类型信息
func reflectType(x interface{}) {
t := reflect.TypeOf(x)
fmt.Printf("Type: %v, Kind: %v\n", t.Name(), t.Kind())
}

type cat struct {
name string
}

type dog struct {
name string
}

//Kind 获取种类 指底层类型
//go语言反射中 数组、切片、map、指针类型的变量 .Name() 返回是空

//reflect.ValueOf 返回的是reflect.Value,其中包含原始值信息
//reflect.Value 与 原始值 可相互转换

func reflectValue(x interface{}) {
v := reflect.ValueOf(x)
k := v.Kind()
switch k {
case reflect.Int64:
fmt.Printf("Type: Int64, Value: %v\n", int64(v.Int()))
}
}

//Elem() 获取指针对应的值
func reflectSetValue(x interface{}) {
//t := reflect.TypeOf(x)
//fmt.Println(t, t.Name(), t.Kind())
v := reflect.ValueOf(x)
//fmt.Println(v, v.Kind())
v.Elem().SetInt(2)
}

//isNil、isValid

//func (v Value) IsNil() bool 检查v持有值是否为nil v持有类型必须是函数、接口、map、指针、切片之一
//func (v Value) IsValid() bool 检查v是否持有值 如果v是Value的零值返回假 此时v只有调用String、Kind方法
//IsNil常用于判断指针是否为空
//IsValid 常用于判断返回值是否有效

//结构体反射
//t := reflect.TypeOf(b)
//如果t的类型是结构体,还有以下方法
//t.Field(1) StructField 返回索引对应结构体字段的信息
//t.NumField() int 返回结构体字段数量
//t.FieldByName(name string) (StructField, bool) 根据指定字符串返回对应结构体字段的信息
//t.FieldByIndex(index []int) StructField 根据[]int提供的每个结构体字段索引返回对应结构体字段的信息
//t.FieldByNameFunc(match func(string) bool) (StructField, bool)
//t.NumMethod() int 返回方法数量
//t.Method(int) Method 返回第几个方法
//t.MethodByName(string) (Method, bool) 根据指定字符串返回具体方法

// StructField 类型 描述结构体中一个字典信息
//type StructField struct {
// Name string // 字段名
// PkgPath string
// Type Type // 字段类型
// Tag StructTag // 字典标签
// Offset uintptr
// Index []int
// Anonymous bool //是否匿名字段
//}

type student struct {
Name string `json:name`
Score int `json:score`
}

//其他包要能调用,首字母必须大写
func (s student) Study() string {
msg := "学习方法"
return msg
}

func (s student) Sleep() string {
msg := "睡觉方法"
return msg
}

func (s student) TestFn(a string) string {
msg := fmt.Sprintf("%s 测试函数返回值", a)
return msg
}

func main() {
//var a int64 = 200
//reflectType(a)
//var b float32 = 3.1415
//reflectType(b)
//c := dog{name: "wangcai"}
//d := cat{name: "huahua"}
//reflectType(c)
//reflectType(d)
//reflectType([3]int{})
//reflectType([]int{})
//reflectType(map[string]int{})
//reflectType(&a)

//var a int64 = 300
//reflectValue(a)
////将整型20转换为reflect.Value类型
//b := reflect.ValueOf(20)
//fmt.Printf("Type b: %T\n", b)

//a := 100
//reflectSetValue(&a)
//fmt.Println(a)

//var a *int
//println(reflect.ValueOf(a).IsNil())
//println(reflect.ValueOf(a).IsValid())

//b := struct {name string; age int}{name:"Ropon", age: 18}
//t := reflect.TypeOf(b)
//fmt.Println(t.Field(1))
//fmt.Println(t.NumField())
//fmt.Println(t.FieldByName("age2"))

//println(reflect.ValueOf(b).IsValid())

//c := map[string]int{"Ropon": 2}
//println(reflect.ValueOf(c).MapIndex(reflect.ValueOf("Ropon")).IsValid())

stu1 := student{
Name: "Ropon",
Score: 99,
}
//t := reflect.TypeOf(stu1)
//fmt.Println(t.Name(), t.Kind())
//for i := 0;i < t.NumField(); i ++ {
// filed := t.Field(i)
// fmt.Println(filed.Name, filed.Index, filed.Type, filed.Tag.Get("json"))
//}
//scoreField, ok := t.FieldByName("Score")
//if ok {
// fmt.Println(scoreField.Name, scoreField.Index, scoreField.Type, scoreField.Tag.Get("json"))
//}

//fmt.Println(t.NumMethod())
v := reflect.ValueOf(stu1)
//for i := 0; i < t.NumMethod(); i++ {
// //fmt.Println(v.Method(i).Type(), t.Method(i).Name)
// //通过反射调用方法传递参数必须是 []reflect.Value类型
// fmt.Println(v.Method(i).Call([]reflect.Value{})[0])
//}
//有参数
res := v.MethodByName("TestFn").Call([]reflect.Value{
reflect.ValueOf("传入变量"),
})
fmt.Println(res[0])
}