Suppose you have a slice declared as:
names := []string{"Manyanda", "Abhishek", "Pawel", "Eoin", "Jameel", "Vincent", "Jason", "Massimo"}
and a printSlice
function that prints the first count
element of the passed in slice implemented like this:
func printSlice(slice []*string, count int) {
for i, val := range slice {
if i < count {
fmt.Println(*val, " rules!!")
} else {
return
}
}
}
Now suppose that to invoke it you use the following code:
// convert names to a slice of string pointers
var ary []*string
for _, val := range names {
ary = append(ary, &val)
}
// Let's print all the names but the last one (Massimo)
printSlice(ary, 7)
The output of the previous code will be:
Massimo rules!!
Massimo rules!!
Massimo rules!!
Massimo rules!!
Massimo rules!!
Massimo rules!!
Massimo rules!!
For performance reasons, go
reuses the loop variable instead of creating a new one on every loop. By adding the address of the loop variable to the slice on each loop, we always added the same address and the variable value will be the last value it has been assigned in the loop (Massimo).
The fix is easy:
// convert names to a slice of string pointers
var ary []*string
for _, val := range names {
tmp := val
ary = append(ary, &tmp)
}
// Let's print all the names but the last one (Massimo)
printSlice(ary, 7)
Now the output will be:
Manyanda rules!!
Abhishek rules!!
Pawel rules!!
Eoin rules!!
Jameel rules!!
Vincent rules!!
Jason rules!!