Zunächst ist der interface{}
-Typ einfach ein Typ, der alle Werte akzeptiert, da es eine Schnittstelle mit einem leeren Methodensatz ist und jeder Typ kann dies erfüllen. int
hat zum Beispiel keine Methoden, auch interface{}
nicht.
Bei einer Methode, die die Werte zweier Variablen vertauscht, müssen Sie zunächst sicherstellen, dass diese Variablen tatsächlich änderbar sind. Werte, die an eine Funktion übergeben werden, werden immer kopiert (außer Referenztypen wie Slices und Karten, aber das ist im Moment nicht unser Anliegen). Sie können modifizierbare Parameter erreichen, indem Sie einen Zeiger auf die Variable verwenden.
Also mit diesem Wissen kannst du weitermachen und SwapNum
so definieren:
Jetzt ist SwapNum
eine Funktion, die zwei Parameter eines beliebigen Typs akzeptiert.
Sie können nicht schreiben
, da dies nur Parameter des Typs *interface{}
und nicht irgendeines Typs akzeptieren würde.
(Probieren Sie es selbst hier ).
Wir haben also eine Signatur, das einzige, was übrig bleibt, ist das Tauschen der Werte.
%Vor% Nein, das wird nicht funktionieren. Durch die Verwendung von interface{}
müssen Laufzeit-Assertions durchgeführt werden, um zu prüfen, ob wir das Richtige tun oder nicht. Daher muss der Code mithilfe des Pakets reflect
erweitert werden. In diesem Artikel können Sie vielleicht anfangen, wenn Sie nicht über Reflektion Bescheid wissen.
Im Grunde brauchen wir diese Funktion:
%Vor% Dieser Code spiegelt a
und b
mithilfe von reflect.ValueOf()
wider, damit wir das tun können
inspiziere es. In der gleichen Zeile gehen wir davon aus, dass wir Zeigerwerte und Dereferenzierung haben
Sie rufen .Elem()
auf.
Dies bedeutet im Grunde genommen ra := *a
und rb := *b
.
Danach erstellen wir eine Kopie von *a
, indem wir den Wert mithilfe von .Interface()
anfordern
und es zuweisen (effektiv eine Kopie).
Schließlich setzen wir den Wert von a
auf b
mit [ra.Set(rb)
] 5 , was in *a = *b
übersetzt
und dann b
zu a
zuweisen, was wir in der temp gespeichert haben. Variable vorher. Dafür,
Wir müssen tmp
zurück in eine Spiegelung von sich selbst konvertieren, damit rb.Set()
verwendet werden kann
(Es dauert ein reflect.Value
als Parameter).
Ja! Wir können den Code typsicherer machen oder besser die Definition von Swap
type sicher machen
mit reflect.MakeFunc
. Im Dokument (folgen Sie dem Link) ist ein Beispiel, das sehr ist
wie das, was du versuchst. Im Wesentlichen können Sie einen Funktionsprototyp mit Inhalt füllen
durch Reflexion. Als Sie den Prototyp (die Signatur) der Funktion zur Verfügung gestellt haben
Compiler kann die Typen überprüfen, was nicht möglich ist, wenn der Wert auf interface{}
reduziert wird.
Beispielverwendung:
%Vor%Der Code dahinter:
%Vor% Der Code von swap
ist im Grunde derselbe wie der von SwapNum
. makeSwap
ist gleich
wie der in den Dokumenten verwendete, wo es ziemlich gut erklärt wird.
Haftungsausschluss: Der obige Code enthält eine Menge Annahmen darüber, was gegeben ist und
wie die Werte aussehen. Normalerweise müssen Sie zum Beispiel prüfen, ob das gegeben ist
Werte in SwapNum
sind tatsächlich Zeigerwerte und so weiter. Ich habe das vergessen
aus Gründen der Übersichtlichkeit.
Tags und Links go