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中文網其他相關文章!