Golang: Schnittstelle zum Tauschen von zwei Zahlen

8

Ich möchte zwei Zahlen über die Schnittstelle austauschen, aber das Interface-Konzept ist für mich so verwirrend.

Ссылка

Das ist der Code und der Spielplatz. Wie verwende ich die Schnittstelle und vertausche zwei Eingangsnummern? Muss ich zwei Strukturen definieren?

%Vor%     
nemo 10.10.2013, 16:54
quelle

1 Antwort

14

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:

%Vor%

Jetzt ist SwapNum eine Funktion, die zwei Parameter eines beliebigen Typs akzeptiert. Sie können nicht schreiben

%Vor%

, 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).

Können wir es besser machen?

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.

    
nemo 10.10.2013, 17:58
quelle

Tags und Links