Go-Zeiger
Zeiger in Go sind ähnlich wie in C, aber einfacher. Zeiger werden verwendet, um Speicheradressen zu speichern.
Was ist ein Zeiger?
Ein Zeiger ist eine Variable, die die Speicheradresse einer anderen Variable speichert. In Go wird ein Zeiger mit * deklariert.
var p *intIn diesem Beispiel ist p ein Zeiger auf einen int-Wert.
Adressoperator
Der Adressoperator & wird verwendet, um die Adresse einer Variable zu erhalten.
func main() {
a := 42
p := &a
fmt.Printf("Adresse von a: %p\n", p)
}Dereferenzierung
Der Dereferenzierungsoperator * wird verwendet, um auf den Wert zuzugreifen, auf den der Zeiger zeigt.
func main() {
a := 42
p := &a
fmt.Println(*p) // 42
*p = 100
fmt.Println(a) // 100
}new-Funktion
Die new-Funktion allokiert Speicher für einen Typ und gibt einen Zeiger darauf zurück.
func main() {
p := new(int)
*p = 42
fmt.Println(*p) // 42
}Zeiger auf Zeiger
Ein Zeiger kann auch auf einen anderen Zeiger zeigen.
func main() {
a := 42
p := &a
pp := &p
fmt.Println(**pp) // 42
}Zeiger und Funktionen
Zeiger können an Funktionen übergeben werden, um Werte zu ändern.
func main() {
a := 42
modify(&a)
fmt.Println(a) // 100
}
func modify(p *int) {
*p = 100
}Zeiger und Strukturen
Zeiger werden häufig mit Strukturen verwendet, um Kopien zu vermeiden.
type Person struct {
Name string
Age int
}
func main() {
p := Person{Name: "Alice", Age: 25}
modifyPerson(&p)
fmt.Println(p.Name) // Bob
}
func modifyPerson(p *Person) {
p.Name = "Bob"
}nil Zeiger
Ein Zeiger, der nicht initialisiert wurde, hat den Wert nil.
func main() {
var p *int
fmt.Println(p) // <nil>
fmt.Println(p == nil) // true
}Zeigerarithmetik
Go unterstützt keine Zeigerarithmetik wie C. Sie können nicht auf Zeigern rechnen.
func main() {
a := 42
p := &a
// p++ // Fehler: invalid operation
}Vergleich von Zeigern
Zeiger können mit == und != verglichen werden.
func main() {
a := 42
p1 := &a
p2 := &a
p3 := new(int)
fmt.Println(p1 == p2) // true
fmt.Println(p1 == p3) // false
}Wann Zeiger verwenden?
Zeiger sollten in folgenden Fällen verwendet werden:
- Wenn Sie den Wert einer Variable in einer Funktion ändern möchten
- Wenn Sie vermeiden möchten, große Strukturen zu kopieren
- Wenn Sie nullable Werte benötigen
type Person struct {
Name string
Age *int // Age kann nil sein
}Zeiger und Slices
Slices sind intern Zeiger auf Arrays. Wenn Sie einen Slice an eine Funktion übergeben, wird nur ein Zeiger kopiert, nicht die gesamten Daten.
func main() {
s := []int{1, 2, 3}
modifySlice(s)
fmt.Println(s) // [100 2 3]
}
func modifySlice(s []int) {
s[0] = 100
}Zeiger und Maps
Maps sind intern Referenztypen. Wenn Sie eine Map an eine Funktion übergeben, wird nur ein Zeiger kopiert.
func main() {
m := map[string]int{"a": 1}
modifyMap(m)
fmt.Println(m) // map[a:100]
}
func modifyMap(m map[string]int) {
m["a"] = 100
}Zeiger und Kanäle
Kanäle sind auch Referenztypen. Wenn Sie einen Kanal an eine Funktion übergeben, wird nur ein Zeiger kopiert.
func main() {
ch := make(chan int)
go send(ch)
fmt.Println(<-ch) // 42
}
func send(ch chan<- int) {
ch <- 42
}