B Best
B Best

Reputation: 1154

Modify slice element using pointer

I'm currently trying to modify an element of a slice by passing a pointer to a function. Outside of the function the element is not modified.

Is there a way to modify the element without passing the slice itself along with the index of the desired element to alter?

package main

import (
    "fmt"
)

type Item struct {
    Value int
}

func alter(t *Item) {
    (*t).Value = 100
}

func main() {

    items := []Item{Item{0}, Item{1}}

    for _, item := range items {
        alter(&item)
    }

    fmt.Println(items) // Output is still [{0} {1}]

}

Golang Playground

Upvotes: 3

Views: 2613

Answers (2)

shmsr
shmsr

Reputation: 4204

Refer: https://tour.golang.org/moretypes/16

The range form of the for loop iterates over a slice or map.

When ranging over a slice, two values are returned for each iteration. The first is the index, and the second is a copy of the element at that index.

So,

for i, x := range arr {
    // x is copy for arr[i]
}

Hence, we will directly used arr[i] and pass the address of the same to the alter function so that it could be modified.

Sample code:

package main

import "fmt"

type Item struct {
    Value int
}

func alter(t *Item) {
    (*t).Value = 100
}

func main() {
    items := []Item{{0}, {1}}

    for i := range items {
        alter(&items[i])
    }

    fmt.Println(items)
}

[Playground]

Upvotes: 4

mkopriva
mkopriva

Reputation: 38213

for i := range items {
    alter(&items[i])
}

Or

items := []*Item{{0}, {1}}

for _, item := range items {
    alter(item)
}

The reason your version doesn't work is because the iteration variable item holds a copy of the element inside the slice, which means that what you're modifying is the copy and not the original. You can see that they are separate objects in memory if you run this: https://play.golang.org/p/vr9CfX0WQcB

Upvotes: 7

Related Questions