Heim  >  Artikel  >  Backend-Entwicklung  >  Gibt es eine gute Möglichkeit, numerische Typen für „method.Call“ in Golang geeignet zu machen?

Gibt es eine gute Möglichkeit, numerische Typen für „method.Call“ in Golang geeignet zu machen?

WBOY
WBOYnach vorne
2024-02-08 23:06:081182Durchsuche

Gibt es eine gute Möglichkeit, numerische Typen für „method.Call“ in Golang geeignet zu machen?

PHP-Editor Youzi In Golang kann es bei Verwendung der method.Call-Methode zum Aufrufen einer Funktion zu Problemen mit numerischen Typparametern kommen. Es gibt jedoch einige Möglichkeiten, wie wir dieses Problem lösen können. Zuerst können wir den numerischen Typ in den entsprechenden Typ „reflect.Value“ konvertieren und ihn dann an die Methode „method.Call“ übergeben. Darüber hinaus können wir auch die Reflexionsmethode verwenden, um den Parametertyp der Funktion zu erhalten und entsprechend dem Parametertyp eine entsprechende Verarbeitung durchzuführen. Kurz gesagt, durch diese Methoden können wir den numerischen Typ für den Aufruf der Methode geeignet machen. Rufen Sie die Methode in Golang auf und lösen Sie so dieses Problem.

Frageninhalt

Code Go Playground:

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})
}

Ausgabe:

func:Func1 a:1 b:2 c:3.000000 
func:Func2 a:test b:1 c:2 d:3

Weil ich die Methode dynamisch aufrufen muss, die Parameter jedoch aus unterschiedlichen Datenformaten stammen, was dazu führt, dass der numerische Typ konvertiert werden muss. Beim Parsen von JSON in Golang wird beispielsweise ein nicht spezifizierter Zahlentyp als float64 behandelt, obwohl es sich wahrscheinlich um einen int handeln sollte.

Der Code sieht schrecklich aus, funktioniert aber gut.

Ich habe mich gefragt, ob es einen besseren Weg gibt, dies zu tun.

Problemumgehung

Verwenden Sie die Reflect-API, um Werte zu konvertieren.

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
}

Um Panik zu verhindern, prüft dieser Code vor der Konvertierung, ob die Konvertierung zulässig ist. Code auf PlayGround ausführen

!

Das obige ist der detaillierte Inhalt vonGibt es eine gute Möglichkeit, numerische Typen für „method.Call“ in Golang geeignet zu machen?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:stackoverflow.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen