代码去游乐场:
package main
import (
"fmt"
"reflect"
)
func (s StructWithManyMethods) Func1(a int, b uint, c float64) {
fmt.Printf("func:Func1 a:%d b:%d c:%f \n", a, b, c)
}
func (s StructWithManyMethods) Func2(a string, b int, c int, d int) {
fmt.Printf("func:Func2 a:%s b:%d c:%d d:%d\n", a, b, c, d)
}
type StructWithManyMethods struct {
}
func (s StructWithManyMethods) CallMethod(n string, p []interface{}) {
method := reflect.ValueOf(s).MethodByName(n)
methodType := method.Type()
for i := 0; i < methodType.NumIn(); i++ {
in := methodType.In(i)
switch in.Kind() {
case reflect.Float32:
switch v := p[i].(type) {
case float64:
p[i] = float32(v)
case float32:
p[i] = float32(v)
case int:
p[i] = float32(v)
case uint:
p[i] = float32(v)
case int8:
p[i] = float32(v)
case uint8:
p[i] = float32(v)
case int16:
p[i] = float32(v)
case uint16:
p[i] = float32(v)
case int32:
p[i] = float32(v)
case uint32:
p[i] = float32(v)
case int64:
p[i] = float32(v)
case uint64:
p[i] = float32(v)
}
case reflect.Float64:
switch v := p[i].(type) {
case float64:
p[i] = float64(v)
case float32:
p[i] = float64(v)
case int:
p[i] = float64(v)
case uint:
p[i] = float64(v)
case int8:
p[i] = float64(v)
case uint8:
p[i] = float64(v)
case int16:
p[i] = float64(v)
case uint16:
p[i] = float64(v)
case int32:
p[i] = float64(v)
case uint32:
p[i] = float64(v)
case int64:
p[i] = float64(v)
case uint64:
p[i] = float64(v)
}
case reflect.Int:
switch v := p[i].(type) {
case float64:
p[i] = int(v)
case float32:
p[i] = int(v)
case int:
p[i] = int(v)
case uint:
p[i] = int(v)
case int8:
p[i] = int(v)
case uint8:
p[i] = int(v)
case int16:
p[i] = int(v)
case uint16:
p[i] = int(v)
case int32:
p[i] = int(v)
case uint32:
p[i] = int(v)
case int64:
p[i] = int(v)
case uint64:
p[i] = int(v)
}
case reflect.Uint:
switch v := p[i].(type) {
case float64:
p[i] = uint(v)
case float32:
p[i] = uint(v)
case int:
p[i] = uint(v)
case uint:
p[i] = uint(v)
case int8:
p[i] = uint(v)
case uint8:
p[i] = uint(v)
case int16:
p[i] = uint(v)
case uint16:
p[i] = uint(v)
case int32:
p[i] = uint(v)
case uint32:
p[i] = uint(v)
case int64:
p[i] = uint(v)
case uint64:
p[i] = uint(v)
}
case reflect.Int8:
switch v := p[i].(type) {
case float64:
p[i] = int8(v)
case float32:
p[i] = int8(v)
case int:
p[i] = int8(v)
case uint:
p[i] = int8(v)
case int8:
p[i] = int8(v)
case uint8:
p[i] = int8(v)
case int16:
p[i] = int8(v)
case uint16:
p[i] = int8(v)
case int32:
p[i] = int8(v)
case uint32:
p[i] = int8(v)
case int64:
p[i] = int8(v)
case uint64:
p[i] = int8(v)
}
case reflect.Uint8:
switch v := p[i].(type) {
case float64:
p[i] = uint8(v)
case float32:
p[i] = uint8(v)
case int:
p[i] = uint8(v)
case uint:
p[i] = uint8(v)
case int8:
p[i] = uint8(v)
case uint8:
p[i] = uint8(v)
case int16:
p[i] = uint8(v)
case uint16:
p[i] = uint8(v)
case int32:
p[i] = uint8(v)
case uint32:
p[i] = uint8(v)
case int64:
p[i] = uint8(v)
case uint64:
p[i] = uint8(v)
}
case reflect.Int16:
switch v := p[i].(type) {
case float64:
p[i] = int16(v)
case float32:
p[i] = int16(v)
case int:
p[i] = int16(v)
case uint:
p[i] = int16(v)
case int8:
p[i] = int16(v)
case uint8:
p[i] = int16(v)
case int16:
p[i] = int16(v)
case uint16:
p[i] = int16(v)
case int32:
p[i] = int16(v)
case uint32:
p[i] = int16(v)
case int64:
p[i] = int16(v)
case uint64:
p[i] = int16(v)
}
case reflect.Uint16:
switch v := p[i].(type) {
case float64:
p[i] = uint16(v)
case float32:
p[i] = uint16(v)
case int:
p[i] = uint16(v)
case uint:
p[i] = uint16(v)
case int8:
p[i] = uint16(v)
case uint8:
p[i] = uint16(v)
case int16:
p[i] = uint16(v)
case uint16:
p[i] = uint16(v)
case int32:
p[i] = uint16(v)
case uint32:
p[i] = uint16(v)
case int64:
p[i] = uint16(v)
case uint64:
p[i] = uint16(v)
}
case reflect.Int32:
switch v := p[i].(type) {
case float64:
p[i] = int32(v)
case float32:
p[i] = int32(v)
case int:
p[i] = int32(v)
case uint:
p[i] = int32(v)
case int8:
p[i] = int32(v)
case uint8:
p[i] = int32(v)
case int16:
p[i] = int32(v)
case uint16:
p[i] = int32(v)
case int32:
p[i] = int32(v)
case uint32:
p[i] = int32(v)
case int64:
p[i] = int32(v)
case uint64:
p[i] = int32(v)
}
case reflect.Uint32:
switch v := p[i].(type) {
case float64:
p[i] = uint32(v)
case float32:
p[i] = uint32(v)
case int:
p[i] = uint32(v)
case uint:
p[i] = uint32(v)
case int8:
p[i] = uint32(v)
case uint8:
p[i] = uint32(v)
case int16:
p[i] = uint32(v)
case uint16:
p[i] = uint32(v)
case int32:
p[i] = uint32(v)
case uint32:
p[i] = uint32(v)
case int64:
p[i] = uint32(v)
case uint64:
p[i] = uint32(v)
}
case reflect.Int64:
switch v := p[i].(type) {
case float64:
p[i] = int64(v)
case float32:
p[i] = int64(v)
case int:
p[i] = int64(v)
case uint:
p[i] = int64(v)
case int8:
p[i] = int64(v)
case uint8:
p[i] = int64(v)
case int16:
p[i] = int64(v)
case uint16:
p[i] = int64(v)
case int32:
p[i] = int64(v)
case uint32:
p[i] = int64(v)
case int64:
p[i] = int64(v)
case uint64:
p[i] = int64(v)
}
case reflect.Uint64:
switch v := p[i].(type) {
case float64:
p[i] = uint64(v)
case float32:
p[i] = uint64(v)
case int:
p[i] = uint64(v)
case uint:
p[i] = uint64(v)
case int8:
p[i] = uint64(v)
case uint8:
p[i] = uint64(v)
case int16:
p[i] = uint64(v)
case uint16:
p[i] = uint64(v)
case int32:
p[i] = uint64(v)
case uint32:
p[i] = uint64(v)
case int64:
p[i] = uint64(v)
case uint64:
p[i] = uint64(v)
}
}
}
parameterValues := make([]reflect.Value, 0)
for _, e := range p {
parameterValues = append(parameterValues, reflect.ValueOf(e))
}
method.Call(parameterValues)
}
func main() {
var s StructWithManyMethods
s.CallMethod("Func1", []interface{}{1.0, 2.0, 3})
s.CallMethod("Func2", []interface{}{"test", 1, 2, 3.0})
}
输出:
func:Func1 a:1 b:2 c:3.000000
func:Func2 a:test b:1 c:2 d:3
因为我需要动态调用方法,但是参数来自不同的数据格式,这就导致需要转换数值类型。例如,在 Golang 中解析 JSON 时,不确定的数字类型被视为 float64,尽管它可能应该是 int。
代码看起来很糟糕,但效果很好。
我想知道是否有更好的方法来做到这一点。
使用 Reflect API 转换值。
func (s StructWithManyMethods) CallMethod(n string, p []interface{}) {
method := reflect.ValueOf(s).MethodByName(n)
methodType := method.Type()
var parameterValues []reflect.Value
for i := 0; i < methodType.NumIn(); i++ {
in := methodType.In(i)
parameterValues = append(parameterValues, reflect.ValueOf(p[i]).Convert(in))
}
method.Call(parameterValues)
}