long blogs

进一步有进一步惊喜


  • Home
  • Archive
  • Tags
  •  

© 2025 long

Theme Typography by Makito

Proudly published with Hexo

go-reflect

Posted at 2020-07-23 golang 反射 

golang反射

反射能做什么?获得运行时变量的值、根据变量名获得变量的值、更改变量的值。动态调用函数。

1、获得变量的类型

reflect.Type中的Kind()函数可以获得反射的变量类型。通过变量类型判断可以选择不同的处理方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// kind处理不同分支
func printType(t reflect.Type) {
switch t.Kind() {
case reflect.Int:
fmt.Println("int")
case reflect.String:
fmt.Println("string")
}
}
func main() {
a := 1
t := reflect.TypeOf(a)
printType(t)
t = reflect.TypeOf("Hello World")
printType(t)
}
2、调用函数
  • 调用无入参出参函数
  • 调用有入参函数
  • 调用有入参和出参函数
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
// 需求:根据一个函数字符串,调用函数,提供函数参数,接收返回值
// 反射调用无参函数
// 反射调用有参无返回值函数
// 反射调用有入参和返回的函数
// 动态调用函数,无参数
type T struct{}
func (t *T) Do(){
fmt.Println("Hello Do")
}
// 有参函数
func (t *T) Do2(a int,b string){
fmt.Println("hello" + b,a)
}
func (t *T) Do3() (string,error){
return "Hello",errors.New("return error")
}
func main() {
// 函数名称
name := "Do"
t := &T{}
// 反射调用函数
reflect.ValueOf(t).MethodByName(name).Call(nil)
// 反射调用有参函数
a := reflect.ValueOf(111)
b := reflect.ValueOf("world")
in := []reflect.Value{a,b}
reflect.ValueOf(t).MethodByName("Do2").Call(in)
// 反射含有返回值的函数
rets := reflect.ValueOf(t).MethodByName("Do3").Call(nil)
fmt.Printf(" strValue:%[1]v \n errValue:%[2]v\n strType:%[1]T \n errType:%[2]T\n",
rets[0],rets[1].Interface().(error))
}
3、获得结构体的特定Tag的值

这个和Java的注解起的作用是类似的。

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
// 反射解析struct 中的tag
//
//
type T struct {
A int `json:"a" test:"testaa"`
B string `json:"b" test:"testbb"`
}
func main() {
t := T{
A: 124,
B: "Hello",
}
tt := reflect.TypeOf(t)
for i:=0;i<tt.NumField();i++{
field := tt.Field(i)

// 输出json 的tag内容
if json,ok := field.Tag.Lookup("json");ok{
fmt.Printf("field: %s,testTag tag:%s\n",field.Name,json)
}

// 输出test的tag内容
if testTag,ok := field.Tag.Lookup("test");ok{
fmt.Printf("field: %s,testTag tag:%s \n",field.Name, testTag)
}
}
}
4、动态注入
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
// 类型转换和赋值
// 将T1中的值赋值给tag为等于T2.
// T1.A -> T2.AA
// T1.B -> T2.BB
// 怎么知道T1.A对应T2.AA?
// T1中有一个tag为T2,值为AA
type T1 struct {
A int `T2:"AA"`
B string `T2:"BB"`
}
type T2 struct {
AA int
BB string
}
func main() {
t := T1{
A: 123,
B: "hello",
}
rT1Type := reflect.TypeOf(t)
rT1Value := reflect.ValueOf(t)

t2 := &T2{}
rT2Value := reflect.ValueOf(t2)

// 赋值
for i:=0;i< rT1Type.NumField();i++{
field := rT1Type.Field(i)
// 获得T1类型中的Tag的值为T2的Tag值
newTTag := field.Tag.Get("T2")
// 获得对应T1中对应Tag的值,为域值
tValue := rT1Value.Field(i)
// 给T2设置值
rT2Value.Elem().FieldByName(newTTag).Set(tValue)
}
fmt.Println(t2)
}
5、查看某个结构体是否实现了某个接口
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
// 动物接口
type Animal interface {
speak()
}
type Cry interface {
cry()
}
// 汽车实现speak()方法
type Car struct {

}
func (c *Car) speak() {
fmt.Println("wu wu wu ...")
}
func main() {
car := &Car{}
rCarType := reflect.TypeOf(car)

animalType := reflect.TypeOf((*Animal)(nil)).Elem()
cryType := reflect.TypeOf((*Cry)(nil)).Elem()

// 判断car是否实现了Animal接口
re := rCarType.Implements(animalType)
fmt.Println(re)
// car 是否实现了Cry接口
re = rCarType.Implements(cryType)
fmt.Println(re)
}

Share 

 Previous post: go-module Next post: go-file 

© 2025 long

Theme Typography by Makito

Proudly published with Hexo