Go: Pointer Fallstricke
Pointer waren mir zwar ein Begriff, allerdings ist die Verwendung in Go an bestimmten Stellen doch etwas spezieller (zumindest für mich).
Normalerweise werden in Go Parameter als Werte (AsValue) übergeben (und nicht als Referenz/Pointer (AsReference)). Eine Ausnahme hierfür stellen folgende vier Typen:
- Slices
- Maps
- Channels
- Interfaces
Diese vier Typen werden immer als Pointer übergeben, ohne dass explizit ein * angegeben werden muss.
Dass Go so viel wie möglich über den Stack lösen will und somit AsValue bevorzugt, zeigt sich auch bei der Verwendung von for range.
l := make([]person, 0)
l = append(l, person{
first: "A",
last: "AA",
}, person{
first: "B",
last: "BB",
})
for i, v := range l {
fmt.Println("Index", i)
v.first = "XX"
fmt.Println("First", v.first)
fmt.Println("First", l[i].first)
}
Man würde auf den ersten Blick erwarten (zumindest wenn man bspw. von C#/JavaScript kommt), dass die Println am Ende das gleiche ausgeben müssten. Tun sie aber nicht, da auch im Zuge von Range die Werte kopiert werden und nicht die ursprüngliche Referenz verwendet wird.
🚨 Somit bei der Verwendung einer for range Schleife, in der Eigenschaften verändert werden, immer darauf achten, dass dies mit Hilfe des ursprünglichen Objektes und dem Index gemacht wird!