Golang:反射的一些操作

1,023 阅读3分钟

1. 对切片的操作

Slice():对切片再切片(两下标)

Slice() 函数与上面所有类型转换的函数都不一样,它返回还是 reflect.Value 反射对象,而不再是我们所想的真实世界里的切片对象。

通过以下示例代码可验证

package main

import (
    "fmt"
    "reflect"
)

func main() {

    var numList []int = []int{1,2}

    v1 := reflect.ValueOf(numList)
    fmt.Printf("转换前, type: %T, value: %v \n", v1, v1)

    // Slice 函数接收两个参数
    v2 := v1.Slice(0, 2)
    fmt.Printf("转换后, type: %T, value: %v \n", v2, v2)
}

输出如下

转换前, type: reflect.Value, value: [1 2]
转换后, type: reflect.Value, value: [1 2]

Slice3():对切片再切片(三下标)

Slice3() 与 Slice() 函数一样,都是对一个切片的反射对象

Set() 和 Append():更新切片

示例代码如下

package main

import (
    "fmt"
    "reflect"
)

func appendToSlice(arrPtr interface{}) {
    valuePtr := reflect.ValueOf(arrPtr)
    value := valuePtr.Elem()

    value.Set(reflect.Append(value, reflect.ValueOf(3)))

    fmt.Println(value)
    fmt.Println(value.Len())
}

func main() {
    arr := []int{1,2}

    appendToSlice(&arr)

    fmt.Println(arr)
}

输出如下

3
[1 2 3]
[1 2 3]

2. 对属性的操作

NumField() 和 Field()

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    name string
    age int
    gender string
}

func (p Person)SayBye()  {
    fmt.Println("Bye")
}

func (p Person)SayHello()  {
    fmt.Println("Hello")
}



func main() {
    p := Person{"写代码的明哥", 27, "male"}

    v := reflect.ValueOf(p)

    fmt.Println("字段数:", v.NumField())
    fmt.Println("第 1 个字段:", v.Field(0))
    fmt.Println("第 2 个字段:", v.Field(1))
    fmt.Println("第 3 个字段:", v.Field(2))

    fmt.Println("==========================")
    // 也可以这样来遍历
    for i:=0;i<v.NumField();i++{
        fmt.Printf("第 %d 个字段:%v \n", i+1, v.Field(i))
    }
}

输出如下

字段数: 3
第 1 个字段: 写代码的明哥
第 2 个字段: 27
第 3 个字段: male
==========================
第 1 个字段:写代码的明哥
第 2 个字段:27
第 3 个字段:male

3. 对方法的操作

NumMethod() 和 Method()

要获取 Name ,注意使用使用 TypeOf

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    name string
    age int
    gender string
}

func (p Person)SayBye()  {
    fmt.Println("Bye")
}

func (p Person)SayHello()  {
    fmt.Println("Hello")
}



func main() {
    p := &Person{"写代码的明哥", 27, "male"}

    t := reflect.TypeOf(p)

    fmt.Println("方法数(可导出的):", t.NumMethod())
    fmt.Println("第 1 个方法:", t.Method(0).Name)
    fmt.Println("第 2 个方法:", t.Method(1).Name)

    fmt.Println("==========================")
    // 也可以这样来遍历
    for i:=0;i<t.NumMethod();i++{
       fmt.Printf("第 %d 个方法:%v \n", i+1, t.Method(i).Name)
    }
}

输出如下

方法数(可导出的): 2
第 1 个方法: SayBye
第 2 个方法: SayHello
==========================
第 1 个方法:SayBye
第 2 个方法:SayHello

4. 动态调用函数(使用索引且无参数)

要调用 Call,注意要使用 ValueOf

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    name string
    age int
}

func (p Person)SayBye() string {
    return "Bye"
}

func (p Person)SayHello() string {
    return "Hello"
}


func main() {
    p := &Person{"wangbm", 27}

    t := reflect.TypeOf(p)
    v := reflect.ValueOf(p)


    for i:=0;i<v.NumMethod();i++{
       fmt.Printf("调用第 %d 个方法:%v ,调用结果:%v\n",
           i+1,
           t.Method(i).Name,
           v.Elem().Method(i).Call(nil))
    }
}

输出如下

调用第 1 个方法:SayBye ,调用结果:[Bye]
调用第 2 个方法:SayHello ,调用结果:[Hello]

5. 动态调用函数(使用函数名且无参数)

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
    name string
    age int
    gender string
}

func (p Person)SayBye()  {
    fmt.Print("Bye")
}

func (p Person)SayHello()  {
    fmt.Println("Hello")
}



func main() {
    p := &Person{"写代码的明哥", 27, "male"}

    v := reflect.ValueOf(p)

    v.MethodByName("SayHello").Call(nil)
    v.MethodByName("SayBye").Call(nil)
}

6. 动态调用函数(使用函数且有参数)

package main

import (
    "fmt"
    "reflect"
)

type Person struct {
}

func (p Person)SelfIntroduction(name string, age int)  {
    fmt.Printf("Hello, my name is %s and i'm %d years old.", name, age)
}



func main() {
    p := &Person{}

    //t := reflect.TypeOf(p)
    v := reflect.ValueOf(p)
    name := reflect.ValueOf("wangbm")
    age := reflect.ValueOf(27)
    input := []reflect.Value{name, age}
    v.MethodByName("SelfIntroduction").Call(input)
}

输出如下

Hello, my name is wangbm and i'm 27 years old.