In Go worden standaard alle functieargumenten per waarde overgedragen: de waarde van de variabele wordt gekopieerd. Maar sommige types (zoals slices, mappen, kanalen) zijn 'wrappers' rond interne structuren (wijzers). Als je een slice per waarde doorgeeft, wordt alleen de beschrijving van de slice gekopieerd en niet de data; beide variabelen verwijzen naar dezelfde array. In het geval van structuren wordt de hele structuur gekopieerd.
Als je kopiëren wilt vermijden en met de originele structuur wilt werken, gebruik je doorgifte per pointer (*Struct).
type User struct { Name string Age int } func updateUser(u User) { u.Age = 30 // verandert alleen de kopie } func updateUserPtr(u *User) { u.Age = 30 // verandert het origineel } func main() { u := User{"Ivan", 25} updateUser(u) fmt.Println(u.Age) // 25 updateUserPtr(&u) fmt.Println(u.Age) // 30 }
Zijn wijzigingen in een slice die aan een functie is doorgegeven altijd zichtbaar buiten de functie?
Nee!
slice[i] = ...), is dit zichtbaar buiten de functie.slice = append(slice, ...)) en het resultaat niet uit de functie wordt geretourneerd, dan zullen de nieuwe elementen in een lokale kopie zitten en zul je ze verliezen.func addElem(s []int) { s = append(s, 100) } func main() { arr := []int{1,2,3} addElem(arr) fmt.Println(arr) // [1 2 3] — 100 is niet toegevoegd }
Verhaal
In een van de projecten werden datastructuren met een groot veld struct (200+ bytes) per waarde verzonden via kanalen tussen goroutines, wat enorme overheadkosten en prestatieverlies veroorzaakte. Na over te schakelen op pointerdoorgifte verminderde de latency met een factor.
Verhaal
In de audit log-service gaf de ontwikkelaar een map (map) door tussen functies zonder expliciete clonering (copy). Wijzigingen aangebracht door de ene functie wijzigden onverwachts gegevens in een ander deel van het programma, wat verwarring in de log veroorzaakte.
Verhaal
In de functie voor dynamische verhoging van de slice werd vergeten de nieuwe slice terug te geven. Hierdoor werden de wijzigingen niet weerspiegeld in de aanroepende code, wat leidde tot verlies van een deel van de transacties. Er werd besloten om de nieuwe slice terug te geven uit de functie.