php小编柚子在golang中,使用method.Call方法调用函数时,对于数字类型参数可能会遇到一些问题。但是,我们可以采用一些方法来解决这个问题。首先,我们可以将数字类型转换为对应的reflect.Value类型,然后再传递给method.Call方法。另外,我们还可以使用反射方法来获取函数的参数类型,并根据参数类型进行相应的处理。总之,通过这些方法,我们可以使数字类型适合golang中的method.Call方法的调用,从而解决这个问题。
代码围棋游乐场:
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{}) error { method := reflect.ValueOf(s).MethodByName(n) methodType := method.Type() parameterValues := make([]reflect.Value, methodType.NumIn()) if len(p) < len(parameterValues) { return fmt.Errorf("expected %d parameters, got %d", len(parameterValues), len(p)) } for i := range parameterValues { in := methodType.In(i) v := reflect.ValueOf(p[i]) if !v.CanConvert(in) { return fmt.Errorf("cannot convert p[%d] from %s to %s", i, v.Type(), in) } parameterValues[i] = reflect.ValueOf(p[i]).Convert(in) } method.Call(parameterValues) return nil }
为了防止出现恐慌,此代码在转换之前检查是否允许转换。
以上是有没有好的方法让数字类型适合golang中的'method.Call”?的详细内容。更多信息请关注PHP中文网其他相关文章!