Ich habe einen Strukturtyp mit einem *int64
Feld.
type SomeType struct {
SomeField *int64
}
Irgendwann in meinem Code möchte ich ein Literal davon deklarieren (sagen wir, wenn ich weiß, dass der Wert 0 sein sollte, oder wenn ich auf eine 0 zeige, wissen Sie, was ich meine)
instance := SomeType{
SomeField: &0,
}
... außer das funktioniert nicht
./main.go:xx: cannot use &0 (type *int) as type *int64 in field value
Also versuche ich das
instance := SomeType{
SomeField: &int64(0),
}
... aber das funktioniert auch nicht
./main.go:xx: cannot take the address of int64(0)
Wie mache ich das? Die einzige Lösung, die ich finden kann, ist die Verwendung einer Platzhaltervariablen
var placeholder int64
placeholder = 0
instance := SomeType{
SomeField: &placeholder,
}
Hinweis: Die Edit: nein tut es nicht. Tut mir leid.&0
Syntax funktioniert einwandfrei, wenn es sich um ein * int anstelle eines handelt *int64
.
Bearbeiten:
Anscheinend war meine Frage zu vieldeutig. Ich bin auf der Suche nach einem Weg , um buchstäblich Zustand ein *int64
. Dies kann innerhalb eines Konstruktors oder zur Angabe von Literalstrukturwerten oder sogar als Argumente für andere Funktionen verwendet werden. Aber Hilfsfunktionen oder die Verwendung eines anderen Typs sind keine Lösungen, nach denen ich suche.
var _ *int64 = pointer.Int64(64)
Antworten:
Die Go Language Specification ( Adreßoperatoren ) erlaubt nicht die Adresse einer numerischen Konstante zu nehmen (nicht von einem nicht typisiert noch eine typisierten Konstante).
Gründe, warum dies nicht zulässig ist, finden Sie in der entsprechenden Frage: Suchen Sie die Adresse der Konstanten in go . Eine ähnliche Frage (die ebenfalls keine Adresse annehmen darf): Wie kann ich einen Verweis auf das Ergebnis einer Operation in Go speichern?
Ihre Optionen (probieren Sie alle auf dem Go-Spielplatz aus ):
1) Mit
new()
Sie können einfach die eingebaute
new()
Funktion verwenden, um einen neuen Nullwert zuzuweisenint64
und seine Adresse zu erhalten:Beachten Sie jedoch, dass dies nur verwendet werden kann, um einen Zeiger auf den Nullwert eines beliebigen Typs zuzuweisen und zu erhalten.
2) Mit Hilfsvariable
Am einfachsten und empfehlenswert für Elemente ungleich Null ist die Verwendung einer Hilfsvariablen, deren Adresse verwendet werden kann:
3) Mit Hilfsfunktion
Hinweis: Hilfsfunktionen zum Erfassen eines Zeigers auf einen Wert ungleich Null sind in meiner
github.com/icza/gox
Bibliothek imgox
Paket verfügbar , sodass Sie diese nicht zu allen Ihren Projekten hinzufügen müssen, wo Sie sie benötigen.Wenn Sie dies mehrmals benötigen, können Sie eine Hilfsfunktion erstellen, die Folgendes zuweist und zurückgibt
*int64
:Und damit:
Beachten Sie, dass wir tatsächlich nichts zugewiesen haben. Der Go-Compiler hat dies getan, als wir die Adresse des Funktionsarguments zurückgegeben haben. Der Go-Compiler führt eine Escape-Analyse durch und weist dem Heap (anstelle des Stacks) lokale Variablen zu, wenn sie der Funktion entkommen können. Weitere Informationen finden Sie unter Ist die Rückgabe eines Slice eines lokalen Arrays in einer Go-Funktion sicher?
4) Mit einer einzeiligen anonymen Funktion
Oder als (kürzere) Alternative:
5) Mit Slice-Literal, Indizierung und Adressierung
Wenn Sie
*SomeField
anders sein möchten als0
, dann brauchen Sie etwas Adressierbares.Sie können das immer noch tun, aber das ist hässlich:
Was hier passiert, ist, dass ein
[]int64
Slice mit einem Literal erstellt wird, das ein Element (5
) enthält. Und es wird indiziert (0. Element) und die Adresse des 0. Elements wird genommen. Im Hintergrund[1]int64
wird auch ein Array von zugewiesen und als Hintergrundarray für das Slice verwendet. Hier gibt es also viel Boilerplate.6) Mit einem Hilfsstrukturliteral
Lassen Sie uns die Ausnahme von den Adressierbarkeitsanforderungen untersuchen:
Dies bedeutet, dass es in Ordnung ist, die Adresse eines zusammengesetzten Literal zu übernehmen, z. B. eines Strukturliterals. Wenn wir dies tun, wird uns der Strukturwert zugewiesen und ein Zeiger darauf erhalten. In diesem Fall steht uns jedoch eine weitere Anforderung zur Verfügung: "Feldauswahl eines adressierbaren Strukturoperanden" . Wenn das Strukturliteral also ein Feld vom Typ enthält
int64
, können wir auch die Adresse dieses Feldes übernehmen!Lassen Sie uns diese Option in Aktion sehen. Wir werden diesen Wrapper-Strukturtyp verwenden:
Und jetzt können wir tun:
Beachten Sie, dass dies
bedeutet folgendes:
Wir können jedoch die "äußere" Klammer weglassen, da der Adressoperator
&
auf das Ergebnis des Selektorausdrucks angewendet wird .Beachten Sie auch, dass im Hintergrund Folgendes passiert (dies ist auch eine gültige Syntax):
7) Mit dem anonymen Strukturliteral des Helfers
Das Prinzip ist das gleiche wie in Fall 6, wir können jedoch auch ein anonymes Strukturliteral verwenden, sodass keine Definition des Strukturtyps für Helfer / Wrapper erforderlich ist:
quelle
instance
Objekte auf zwei verschiedeneint64
s verweisen würden . Aber es scheint die Absicht der OP angemessen zu erfüllen&[]int64{2}[0]
, fühle ich mich wie auf der Grundlage der Beschreibung der Konstanten bei blog.golang.org/constants dies sollte nur Arbeit als&0
.instance
Objekte auf dasselbe zeigenint64
und eines das spitze Objekt modifizieren würde, würden sich beide ändern. Und was ist, wenn Sie jetzt dasselbe Literal verwenden, um ein drittes zu erstelleninstance
? Dieselbe Adresse würde jetzt auf einen anderenint64
Wert verweisen ... daher sollte eine andere Adresse verwendet werden, aber warum sollte im Fall der ersten 2 dieselbe Adresse verwendet werden?Verwenden Sie eine Funktion, die eine Adresse einer int64-Variablen zurückgibt, um das Problem zu lösen.
quelle