在实际工程中,虽然使用reflect会影响性能并且降低代码的可读性,但是reflect能做到代码的动态性和灵活性,因此也被工程上广泛使用,接下里列举几个reflect的应用示例
1. 实现通用的数据序列化和反序列化
go
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type Person struct {
Name string
Age int
}
func serialize(obj interface{}) ([]byte, error) {
value := reflect.ValueOf(obj)
if value.Kind()!= reflect.Struct {
return nil, fmt.Errorf("input is not a struct")
}
data := make(map[string]interface{})
typeOfObj := value.Type()
for i := 0; i < value.NumField(); i++ {
fieldValue := value.Field(i)
fieldType := typeOfObj.Field(i)
data[fieldType.Name] = fieldValue.Interface()
}
return json.Marshal(data)
}
func main() {
p := Person{Name: "Alice", Age: 25}
serializedData, err := serialize(p)
if err!= nil {
fmt.Println(err)
return
}
fmt.Println(string(serializedData))
}
2. 动态调用
go
package main
import (
"fmt"
"reflect"
)
type Calculator struct{}
func (c Calculator) Add(a, b int) int {
return a + b
}
func invokeMethod(obj interface{}, methodName string, params...interface{}) {
value := reflect.ValueOf(obj)
method := value.MethodByName(methodName)
if!method.IsValid() {
fmt.Println("Method not found")
return
}
in := make([]reflect.Value, len(params))
for i, param := range params {
in[i] = reflect.ValueOf(param)
}
result := method.Call(in)
fmt.Println(result[0].Interface())
}
func main() {
c := Calculator{}
invokeMethod(c, "Add", 5, 3)
}
3. 构建动态数据处理管道
go
package main
import (
"fmt"
"reflect"
)
type Processor interface {
Process(data interface{}) interface{}
}
type DoubleProcessor struct{}
func (d DoubleProcessor) Process(data interface{}) interface{} {
if num, ok := data.(int); ok {
return num * 2
}
return data
}
func processData(data interface{}, processors []Processor) interface{} {
value := reflect.ValueOf(data)
for _, processor := range processors {
pValue := reflect.ValueOf(processor)
method := pValue.MethodByName("Process")
in := []reflect.Value{value}
result := method.Call(in)
value = result[0]
}
return value.Interface()
}
func main() {
processors := []Processor{DoubleProcessor{}}
result := processData(5, processors)
fmt.Println(result)
}