go-doc-反射

基本介绍

  1. 反射可以在运行时动态获取变量的各种信息,比如变量的类型,别名
  2. 如果是结构体变量,还可以获取到结构体本身的信息(包括结构体的字段、方法)
  3. 通过反射,可以修改变量的值,可以调用关联的方法
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
package main 

import (
"fmt"
"reflect"
)

type Student struct {
Name string `json:"name"`
Age int `json:"age"`
Score float32 `json:"分数"`
Sex string
}

func (s Student) GetSum(n1 int, n2 int) int {
return n1 + n2
}

func (s Student) Set(name string, age int, score float32, sex string) {
s.Name = name
s.Age = age
s.Score = score
s.Sex = sex
}

func (s Student) Print() {
fmt.Println("---start~----")
fmt.Println(s)
fmt.Println("---end~----")
}

func TestStruct(a interface{}) {

aType := reflect.TypeOf(a)
aVal := reflect.ValueOf(a)
aKind := aVal.Kind()

if aKind != reflect.Struct {
fmt.Println("操作失败,参数不是结构体")
return
}

// 获取字段数量
fNum := aVal.NumField()
fmt.Println("结构体字段数量", fNum)

// 遍历结构体所有字段
for i := 0; i < fNum; i++ {
fmt.Printf("字段 %d 的值为 %v\n", i, aVal.Field(i))

// 显示json的tag
tagVal := aType.Field(i).Tag.Get("json")
if tagVal != "" {
fmt.Printf("字段 %d 的tag为 %v \n", i, tagVal)
}
}

// 获取方法数量
mNum := aVal.NumMethod()
fmt.Println("结构体方法数量", mNum)

// 调用方法
// 方法是根据方法名字排序的
// 这里调用的是 Print
aVal.Method(1).Call(nil)

//
var params []reflect.Value
params = append(params, reflect.ValueOf(10))
params = append(params, reflect.ValueOf(40))
res := aVal.Method(0).Call(params)
fmt.Println("res=", res[0].Int())
}

func main() {
var s Student = Student {
Name : "学生1",
Age : 400,
Score : 30.5,
}

TestStruct(s)
}

反射调用方法

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
package main

import (
"fmt"
"reflect"
"log"
)

func main() {
//调用无参方法
reflectInterface(testReflectParam,nil)

//调用有参方法
reflectInterface(testReflectParam2,getValues(5,"Hello"))

}

// 根据参数获取对应的Values
func getValues(param ...interface{}) []reflect.Value {
vals := make([]reflect.Value,0,len(param))
for i := range param {
vals = append(vals,reflect.ValueOf(param[i]))
}
return vals
}


func reflectInterface(funcInter interface{},paramsValue []reflect.Value) {
v := reflect.ValueOf(funcInter)
if v.Kind() != reflect.Func {
log.Fatal("funcInter is not func")
}

values := v.Call(paramsValue) //方法调用并返回值
for i := range values {
fmt.Println(values[i])
}
}

// 无参方法
func testReflectParam() (string,string){
return "hello world","你好!"
}

// 有参方法
func testReflectParam2(i int,s string) (int,string){
i++
return i,s
}