Zeiger-Grundlagen in Go
Teil des Abschnitts Objektorientierte Programmierung der GO-Journey von Coddy — Lektion 19 von 107.
Ein Pointer (Zeiger) ist eine Variable, die die Speicheradresse einer anderen Variablen speichert. Anstatt einen Wert direkt zu speichern, enthält er den Ort, an dem dieser Wert im Speicher abgelegt ist. Pointer sind grundlegend für Go und unerlässlich für eine effiziente Datenmanipulation.
Um einen Pointer zu erstellen, verwenden Sie den &-Operator, um die Adresse einer Variablen zu erhalten, und den *-Operator, um einen Pointer-Typ zu deklarieren oder auf den Wert an dieser Adresse zuzugreifen.
x := 42
p := &x // p hält die Speicheradresse von x
fmt.Println(p) // 0xc000018030 (Speicheradresse)
fmt.Println(*p) // 42 (Wert an dieser Adresse)Der &-Operator bedeutet „Adresse von“ und gibt einen Pointer zurück. Der *-Operator bedeutet, wenn er auf einen Pointer angewendet wird, „Wert an der Adresse“ und wird als Dereferenzierung bezeichnet. Sie können den ursprünglichen Wert auch über den Pointer ändern.
x := 10
p := &x
*p = 25 // Wert über Pointer ändern
fmt.Println(x) // 25 (Originalvariable geändert)Der Zeigertyp wird als *T geschrieben, wobei T der Typ ist, auf den gezeigt wird. Ein Zeiger auf ein int hat den Typ *int.
var p *int // deklariert einen Zeiger auf int
x := 100
p = &x // p zeigt nun auf xDer Nullwert eines Pointers ist nil, was bedeutet, dass er auf nichts zeigt. Der Versuch, einen nil-Pointer zu dereferenzieren, verursacht eine Runtime-Panic, stellen Sie daher immer sicher, dass Pointer vor der Verwendung initialisiert werden.
Aufgabe
EinfachLassen Sie uns einen einfachen Wertetauscher bauen, der die Mächtigkeit von Pointern demonstriert, um Variablen über ihre Speicheradressen zu verändern.
Sie werden Ihren Code auf zwei Dateien aufteilen:
swap.go: Erstellen Sie eine Funktion namensSwapValues, die zwei*intPointer als Parameter entgegennimmt. Diese Funktion soll die Werte vertauschen, auf die diese Pointer zeigen – nach dem Aufruf sollte jede Variable den ursprünglichen Wert der anderen enthalten. Die Funktion gibt nichts zurück; sie modifiziert die Werte direkt über die Pointer.main.go: Lesen Sie zwei Ganzzahlen von der Eingabe ein, speichern Sie diese in Variablen und verwenden Sie dann IhreSwapValues-Funktion, um deren Werte zu vertauschen. Geben Sie beide Werte vor und nach dem Tausch aus, um die Änderung anzuzeigen.
Die folgenden Eingaben werden bereitgestellt:
- Zeile 1: Erste Ganzzahl
- Zeile 2: Zweite Ganzzahl
Ausgabeformat:
Before: a=[first] b=[second]
After: a=[first] b=[second]Zum Beispiel, gegeben 10 und 25, sollte Ihre Ausgabe wie folgt aussehen:
Before: a=10 b=25
After: a=25 b=10Denken Sie daran, den &-Operator zu verwenden, wenn Sie Ihre Variablen an die Funktion übergeben, und den *-Operator innerhalb der Funktion, um auf die tatsächlichen Werte zuzugreifen und diese zu modifizieren.
Spickzettel
Ein Pointer (Zeiger) ist eine Variable, die die Speicheradresse einer anderen Variable speichert. Verwenden Sie den &-Operator, um die Adresse einer Variable zu erhalten, und den *-Operator, um einen Pointer-Typ zu deklarieren oder auf den Wert an dieser Adresse zuzugreifen.
x := 42
p := &x // p hält die Speicheradresse von x
fmt.Println(p) // 0xc000018030 (Speicheradresse)
fmt.Println(*p) // 42 (Wert an dieser Adresse)Der &-Operator bedeutet "Adresse von" und gibt einen Pointer zurück. Der *-Operator bedeutet, wenn er auf einen Pointer angewendet wird, "Wert an" und wird als Dereferenzierung bezeichnet.
Sie können den ursprünglichen Wert über den Pointer ändern:
x := 10
p := &x
*p = 25 // Wert über Pointer ändern
fmt.Println(x) // 25 (ursprüngliche Variable geändert)Der Pointer-Typ wird als *T geschrieben, wobei T der Typ ist, auf den gezeigt wird:
var p *int // deklariert einen Pointer auf int
x := 100
p = &x // p zeigt nun auf xDer Nullwert eines Pointers ist nil. Der Versuch, einen nil-Pointer zu dereferenzieren, führt zu einer Runtime-Panic.
Probier es selbst
package main
import "fmt"
func main() {
// Lies zwei Ganzzahlen von der Eingabe
var a, b int
fmt.Scanln(&a)
fmt.Scanln(&b)
// Werte vor dem Tausch ausgeben
fmt.Printf("Before: a=%d b=%d\n", a, b)
// TODO: Rufe die Funktion SwapValues mit Pointern auf a und b auf
// Denke daran, den & Operator zu verwenden, um Adressen zu übergeben
// Werte nach dem Tausch ausgeben
fmt.Printf("After: a=%d b=%d\n", a, b)
}
Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.
Alle Lektionen in Objektorientierte Programmierung
1Grundlagen der Go OOP
Externe DateienGo Workspace & ModulePackages & ImportsExportierte vs. nicht-exportierte NamenEinführung in OOP in GoStructs als KlassenMethoden für Structs definierenPointer- vs. Value-ReceiverStruct-InitialisierungKonstruktor-FunktionenZusammenfassung – Einfacher Taschenrechner4Interfaces
Einführung in InterfacesImplizite ImplementierungInterface als VertragLeeres Interface (any)Type AssertionType SwitchInterface-KompositionStringer & Error InterfacesRückblick - Formen-Rechner7Kapselung
Exportierte vs. nicht exportierte FelderKapselung auf Paket-EbeneGetter- & Setter-MethodenInformation Hiding in GoZusammenfassung - Studierendendatensätze10Generics (Go 1.18+)
Einführung in GenericsTypparameterType ConstraintsGenerische StructsWorkaround für generische MethodenZusammenfassung – Generische Collection2Vertiefung: Typen & Structs
Basis- & zusammengesetzte TypenBenutzerdefinierte TypdefinitionenStruct TagsAnonyme StructsVerschachtelte StructsZero Values & StandardwerteZusammenfassung - Kontaktbuch5Komposition statt Vererbung
Warum Go keine Vererbung hatGrundlagen des Struct EmbeddingMethod PromotionEinbetten mehrerer StructsEmbedding vs. AggregationShadowing eingebetteter MethodenZusammenfassung – Mitarbeiter-Hierarchie8Fehlerbehandlung & OOP
Das error-InterfaceEigene FehlertypenError Wrapping (fmt.Errorf)Sentinel-Fehlererrors.Is() und errors.As()Panic, Defer und RecoverZusammenfassung – Datei-Parser3Zeiger & Speicher
Zeiger-Grundlagen in GoZeiger auf StructsWertübergabe vs. ReferenzübergabeDie new() FunktionGarbage Collection in GoWiederholung – Linked List Builder6Polymorphismus in Go
Polymorphismus über InterfacesDuck Typing in GoInterface-ErfüllungsregelnPolymorphe CollectionsDependency InjectionZusammenfassung – Payment Processor9Nebenläufigkeit & OOP
Goroutines GrundlagenChannels & KommunikationGepufferte vs. ungepufferte ChannelsSelect-Anweisungsync.Mutex & sync.RWMutexsync.WaitGroupThread-sicheres Struct-DesignZusammenfassung - Worker Pool