golang reflect

go语言中reflect反射机制。详细原文:地址

接口值到反射对象

package main

import (
    "fmt"
    "reflect"
)

func main() {
    var x int = 1
    fmt.Println("type: ", reflect.TypeOf(x))
}
type:  int
TypeOf
func TypeOf(i interface {}) Type
ValueOfValue
var x int = 1
fmt.Println("value: ", reflect.ValueOf(x))
value:  <int Value>
Kind
fmt.Println("Kind:  ", reflect.ValueOf(x).Kind())
fmt.Println("Kind is Int? ", reflect.ValueOf(x).Kind() == reflect.int)
Kind:   int
Kind is Int?  true

反射对象到接口值

Interface
func (v Value) Interface() interface {}
// Interface 以 interface{} 返回 v 的值
y := v.Interface().(float64)
fmt.Println(y)

修改反射对象

修改反射对象的前提条件是其值必须是可设置的

var x float64 = 3.4
v := reflect.ValueOf(x)
v.SetFloat(7.3) // Error: panic
CanSet
var x float64 = 3.4
v := reflect.ValueOf(x)
fmt.Println("settability of v: ", v.CanSet())
settability of v: false
参数传递reflect.ValueOf(x)reflect.ValueOf(&x)

var x float64 = 3.4
p := reflect.ValueOf(&x) // 获取x的地址
fmt.Println("settability of p: ", p.CanSet())
v := p.Elem()
fmt.Println("settability of v: ", v.CanSet())
v.SetFloat(7.1)
fmt.Println(v.Interface())
fmt.Println(x)
settability of p: false
settability of v: true
7.1
7.1

获取结构体标签

首先介绍如何遍历结构体字段内容,
假设结构体如下,

type T struct {
    A int
    B string
}

t := T{12, "skidoo"}

从而,通过反射来遍历所有的字段内容

s := reflect.ValueOf(&t).Elem()
typeOfT := s.Type()
for i := 0; i < s.NumField(); i++ {
    f := s.Field(i)
    fmt.Printf("%d %s %s = %v\n", i, typeOfT.Field(i).Name, f.Type(), f.Interface())
}
0 A int = 23
1 B string = skidoo

接下来,如何获取结构体的标签内容?

func main() {
    type S struct {
        F string `species:"gopher" color:"blue"`
    }

    s := S{}
    st := reflect.TypeOf(s)
    field := st.Field(0)
    fmt.Println(field.Tag.Get("color"), field.Tag.Get("species"))
}

interface{}到函数反射

map
package main

import "fmt"

func say(text string) {
    fmt.Println(text)
}

func main() {
    var funcMap = make(map[string]func(string))
    funcMap["say"] = say
    funcMap["say"]("hello")
}
map
package main

import "fmt"

func say(text string) {
    fmt.Println(text)
}

func main() {
    var funcMap = make(map[string]interface{})
    funcMap["say"] = say
    funcMap["say"]("hello")
}
cannot call non-function funcMap["say"] (type interface {})

直接调用会报错,提示不能调用interface{}类型的函数。

reflect
package main

import (
    "fmt"
    "reflect"
)

func say(text string) {
    fmt.Println(text)
}

func Call(m map[string]interface{}, name string, params ... interface{}) (result []reflect.Value) {
    f := reflect.ValueOf(m[name])
    in := make([]reflect.Value, len(params))
    for k, param := range params {
        in[k] = reflect.ValueOf(param)
    }
    result = f.Call(in)
    return
}

func main() {
    var funcMap = make(map[string]interface{})
    funcMap["say"] = say
    Call(funcMap, "say", "hello")