Heim  >  Artikel  >  Backend-Entwicklung  >  Rufen Sie den Typnamen einer generischen Struktur ohne Typparameter ab

Rufen Sie den Typnamen einer generischen Struktur ohne Typparameter ab

王林
王林nach vorne
2024-02-13 12:27:071142Durchsuche

Rufen Sie den Typnamen einer generischen Struktur ohne Typparameter ab

In diesem Artikel stellt Ihnen der PHP-Editor Strawberry vor, wie Sie den Typnamen einer generischen Struktur ohne Typparameter erhalten. Generics sind eine leistungsstarke Programmiertechnik, die es Ihnen ermöglicht, generischen Code zu schreiben, ohne bestimmte Typen anzugeben. Manchmal müssen wir jedoch möglicherweise den Typnamen einer generischen Struktur abrufen, ohne bestimmte Typparameter zu enthalten. Dieser Artikel beantwortet diese Frage ausführlich für Sie und hilft Ihnen, generische Programmierung besser zu verstehen und anzuwenden.

Frageninhalt

Angenommen, ich habe einen bestimmten Typ namens foo 的通用结构,我从中创建了两个对象。我可以使用 reflect.typeof(), der jeden wie folgt identifiziert:

package main

import (
    "fmt"
    "reflect"
)

type foo[t any] struct {
    data t
}

func main() {
    a := foo[string]{"cheese"}
    b := foo[int]{42}

    fmt.println(reflect.typeof(a))
    fmt.println(reflect.typeof(b))
}

// main.foo[string]
// main.foo[int]

Ich bin daran interessiert, den gemeinsamen Typ (d. h. foo),而不是具体类型(即 foo[string]foo[int]) dieser Objekte zu bestimmen. Ist das möglich oder muss ich den generischen Typ manuell aus diesen Zeichenfolgen extrahieren (z. B. mithilfe regulärer Ausdrücke)?

Bearbeiten

Ein regulärer Ausdruck könnte so aussehen:

func GetGenericType(x any) string {
    // Get type as a string
    s := reflect.TypeOf(x).String()

    // Regex to run
    r := regexp.MustCompile(`\.(.*)\[`)

    // Return capture
    return r.FindStringSubmatch(s)[1]
}


fmt.Println(GetGenericType(a))
fmt.Println(GetGenericType(b))

// foo
// foo

Ich habe diese Frage auch gesehen, aber das beantwortet die Frage nicht, weil sie den spezifischen Typ (d. h. main.foo[string])而不是通用类型(即, foo) angibt.

Problemumgehung

Reflection kann den Namen eines generischen „Basis“-Typs nicht sehen, da der Basistyp zur Laufzeit nicht vorhanden ist.

Der relevante Absatz in der

go-Spezifikation ist instantiation:

Das Instanziieren eines Typs erzeugt einen neuen nicht-generischen benannten Typ; das Instanziieren einer Funktion erzeugt eine neue nicht-generische Funktion.

Wenn du also schreibst:

b := foo[int]{42}
name := reflect.typeof(b).name()

Der Name des Typs ist genau foo[int].

Es ist erwähnenswert, dass ein Bezeichner foo ohne Typargumentliste zur Kompilierungszeit relevant ist, da er verhindert, dass Sie ihn im selben Paket erneut deklarieren. Typdefinition:

Typdefinition erstellt einen neuen, anderen Typ mit demselben Typ Der zugrunde liegende Typ und die zugrunde liegende Operation werden als Typ und Grenze angegeben Bezeichner, Typname, geben Sie ihn ein .

typedef = identifier [ typeparameters ] type .

Aber wie oben erwähnt, erzeugt die Instanziierung einen neuen benannten Typ, der sich von foo unterscheidet. Zur Laufzeit beschäftigen Sie sich nur mit der Instanziierung, wenn Sie Reflektion verwenden können.

Zusammenfassend denke ich, dass Ihre Regex-Lösung akzeptabel ist, bis einige Hilfsfunktionen zu stdlib hinzugefügt werden (falls vorhanden). Aus Gründen der Klarheit hier erneut posten:

func getgenerictype(x any) string {
    // get type as a string
    s := reflect.typeof(x).string()

    // regex to run
    r := regexp.mustcompile(`\.(.*)\[`)

    // return capture
    return r.findstringsubmatch(s)[1]
}

Denken Sie an den Unterschied zwischen type.string()type.name(): Jeder Typ kann eine Zeichenfolgendarstellung haben, aber nur benannte Typen haben Namen. (Offensichtlich, oder?). Wenn Sie zum Beispiel geschrieben haben:

b := &foo[int]{42}

Dann gibt b的类型为*foo[int],为匿名复合类型,name() eine leere Zeichenfolge zurück.

Das obige ist der detaillierte Inhalt vonRufen Sie den Typnamen einer generischen Struktur ohne Typparameter ab. 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