I have struct with array in it as example below
type WorkPlace struct {
Employees []struct {
Name string `json:"name"`
Salary int `json:"salary"`
Married bool `json:"married"`
} `json:"employees"`
}
{
"employees": [
{
"name": "sonoo1",
"salary": 49000,
"married": true
},
{
"name": "sonoo2",
"salary": 59000,
"married": true
}
]
}
and let say I wanna change the value of Salary while iterating over the slice of Employees.
So way that allow me to modify the fields in that struct is that i have to use the standard for loop
as example which works:
for i := 0; i < len(myWorkPlace.Employees); i {
rise := rand.Intn(100) i
myWorkPlace.Employees[i].Salary = rise
}
but if i do "same thing" with using range
the values are not changed:
for i, v := range myWorkPlace.Employees {
rise := rand.Intn(100) i
v.Salary = rise
}
from what i am reading i see that range
is doing a copy of the array/slice that why the values are not modified ... BUT is there way to access the array/slice or tell range to do this on same array/slice (by using pointers ??) so i can modify the field as in first loop ?
https://go.dev/ref/spec#RangeClause
CodePudding user response:
Please check this two ways
package main
import (
"fmt"
)
type Student struct {
Name string
Marks int
}
func main() {
// slice of non-pointers
students := []Student{Student{Name: "A", Marks: 10}, Student{Name: "B", Marks: 12}, Student{Name: "C", Marks: 14}}
fmt.Printf("Before Update==%v", students)
//using range to update non-pointer struct
for i, v := range students {
students[i].Marks = v.Marks 2
}
fmt.Printf("\nAfter Update==%v", students)
// slice of pointers
studentsV2 := []*Student{&Student{Name: "A", Marks: 10}, &Student{Name: "B", Marks: 12}, &Student{Name: "C", Marks: 14}}
fmt.Println("\nBefore Update==")
for _, v := range studentsV2 {
fmt.Printf("%v", v)
}
//using range to update pointer struct
for _, v := range studentsV2 {
v.Marks = v.Marks 2
}
fmt.Println("\nAfter Update==")
for _, v := range studentsV2 {
fmt.Printf("%v", v)
}
}
CodePudding user response:
@Pratheesh M please have look at this example which is showing the problem which i did ask above:
package main
import (
"encoding/json"
"fmt"
"math/rand"
)
type WorkPlace struct {
Employees []Employees `json:"employees"`
}
type Employees struct {
Name string `json:"name"`
Salary int `json:"salary"`
Married bool `json:"married"`
}
var (
pln = fmt.Println
pf = fmt.Printf
)
func main() {
myWorkPlace := WorkPlace{
[]Employees{
{
Name: "sonoo1",
Salary: 49000,
Married: true,
},
{
Name: "sonoo2",
Salary: 59000,
Married: true,
},
},
}
j, _ := myWorkPlace.Pretty()
pf("Before Update: \n%v\n", j)
for i, v := range myWorkPlace.Employees {
rise := rand.Intn(100) i
v.Salary = rise
}
j1, _ := myWorkPlace.Pretty()
pf("After Update using range: \n%v\n", j1)
for i := 0; i < len(myWorkPlace.Employees); i {
rise := rand.Intn(100) i
myWorkPlace.Employees[i].Salary = rise
}
j2, _ := myWorkPlace.Pretty()
pf("After Update without of range: \n%v\n", j2)
}
func (wp *WorkPlace) Pretty() (string, error) {
j, err := json.MarshalIndent(&wp, " ", " ")
if err != nil {
return "", err
}
return string(j), nil
}
Output:
Before Update:
{
"employees": [
{
"name": "sonoo1",
"salary": 49000,
"married": true
},
{
"name": "sonoo2",
"salary": 59000,
"married": true
}
]
}
After Update using range:
{
"employees": [
{
"name": "sonoo1",
"salary": 49000,
"married": true
},
{
"name": "sonoo2",
"salary": 59000,
"married": true
}
]
}
After Update without of range:
{
"employees": [
{
"name": "sonoo1",
"salary": 49047,
"married": true
},
{
"name": "sonoo2",
"salary": 59060,
"married": true
}
]
}
https://go.dev/play/p/xgENiLIdISG
So my question is still same or maybe i did get what you @Pratheesh M trying to show me with your example ... so maybe you could apply your idea to my code example and make the for
loop "working as expected".