Golang Gotcha: Modifying an array of structs
source link: https://blog.davidvassallo.me/2022/05/11/golang-gotcha-modifying-an-array-of-structs/
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
Golang Gotcha: Modifying an array of structs
Scenario
Using Golang, we initialize an array of structs, within which we’d like to change a field by iterating over the initialized array. This would be necessary (for example) to initialize certain struct fields.
An initial pass at the code may look something like this:
// play with this code here: https://go.dev/play/p/VH0duYxZVZn package main import "fmt" type DemoType struct { Test string } var DemoTypeArray = []DemoType{ DemoType{ Test: "asdfg", }, DemoType{ Test: "qwerty", }, } func main() { fmt.Printf("==================================\nCycling and 'modifying':\n==================================\n") for _, demoTypeInstance := range DemoTypeArray { fmt.Println(demoTypeInstance.Test) demoTypeInstance.Test = "modified" } fmt.Printf("==================================\nAfter 'modification':\n==================================\n") for _, demoTypeInstance := range DemoTypeArray { fmt.Println(demoTypeInstance.Test) } } |
The output of the above code playground ( https://go.dev/play/p/VH0duYxZVZn ) would show:
================================== Cycling and 'modifying': ================================== asdfg qwerty ================================== After 'modification': ================================== asdfg qwerty |
The below line should modify the “Test” field of each struct to “modified”:
demoTypeInstance.Test = "modified"
But clearly that didn’t happen. What gives? In more complex programs this could end up leading to a panic due to a nil reference. A careful inspection of the code reveals the culprit is the for loop. The “range” command outputs two variables… the index of a given item in an array and a copy of the item in the array.
That last comment is key. In our for loop, we are actually modifying the copy of the data, not the data item in the array itself. A solution is to use the index to modify the actual data item, as follows:
// play with this code here: https://go.dev/play/p/NA089ZOURdr package main import "fmt" type DemoType struct { Test string } var DemoTypeArray = []DemoType{ DemoType{ Test: "asdfg", }, DemoType{ Test: "qwerty", }, } func main() { fmt.Printf("==================================\nCycling and 'modifying':\n==================================\n") for idx, demoTypeInstance := range DemoTypeArray { fmt.Println(demoTypeInstance.Test) DemoTypeArray[idx].Test = "modified" } fmt.Printf("==================================\nAfter 'modification':\n==================================\n") for _, demoTypeInstance := range DemoTypeArray { fmt.Println(demoTypeInstance.Test) } } |
The output of the above code playground ( https://go.dev/play/p/NA089ZOURdr ) would show:
================================== Cycling and 'modifying': ================================== asdfg qwerty ================================== After 'modification': ================================== modified modified |
Success! Note the following in the modified code:
- In our for loop, we no longer ignore the index argument, we now store it in “idx”
- To modify the item stored in the array we user the idx variable to directly reference the item within the array
Related
Posted in development, golangTagged development, golang
Post navigation
Recommend
About Joyk
Aggregate valuable and interesting links.
Joyk means Joy of geeK