Heim > Backend-Entwicklung > Golang > 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
Freigeben: 2024-02-08 23:06:08
nach vorne
1208 Leute haben es durchsucht

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})
}
Nach dem Login kopieren

Ausgabe:

func:Func1 a:1 b:2 c:3.000000 
func:Func2 a:test b:1 c:2 d:3
Nach dem Login kopieren

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
}
Nach dem Login kopieren

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!

Quelle:stackoverflow.com
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage