Range references instead values

PointersReferenceGo

Pointers Problem Overview


I saw that range returns the key and the "copy" of the value. Is there a way for that range to return the address of the item? Example

package main

import "fmt"

type MyType struct {
	field string
}

func main() {
    var array [10]MyType

    for _, e := range array {
    	e.field = "foo"
    }

    for _, e := range array {
    	fmt.Println(e.field)
    	fmt.Println("--")
	}
}

http://play.golang.org/p/AFOGG9NGpx

Here "field" is not modified because range sends the copy of field. Do I have to use index or is there any other way to modify the value?

Pointers Solutions


Solution 1 - Pointers

The short & direct answer: no, use the array index instead of the value

So the above code becomes:

package main

import "fmt"

type MyType struct {
    field string
}

func main() {
    var array [10]MyType

    for idx, _ := range array {
        array[idx].field = "foo"
    }

    for _, e := range array {
        fmt.Println(e.field)
        fmt.Println("--")
    }
}

Solution 2 - Pointers

To combine @Dave C and @Sam Toliman's comments

package main

import "fmt"

type MyType struct {
    field string
}

func main() {
    var array [10]MyType

    for idx := range array {
        e := &array[idx]
        e.field = "foo"
    }

    for _, e := range array {
        fmt.Println(e.field)
        fmt.Println("--")
    }
}

https://play.golang.org/p/knKfziB1nce

Solution 3 - Pointers

Go's range only supports assignment by value. There is no &range because the problem it solves is too trivial.

The desired effect can be achieved as follows:

for i := range array {
    e := &array[i]
    e.field = "foo"
}

Solution 4 - Pointers

package main

import "fmt"

type MyType struct {
    field string
}

func main() {
    var array [10]MyType

    for index, _ := range array {
        array[index].field = "foo"
    }

    for _, e := range array {
        fmt.Println(e.field)
        fmt.Println("--")
    }
}

Solution 5 - Pointers

type arrType []string
type refArrType []*string

func ref(arr arrType) refArrType {
	refs := make(refArrType, len(arr))
	for i := 0; i < len(arr); i++ {
		refs[i] = &arr[i]
	}
	return refs
}

func main() {
	arr := arrType{"hello", "world"}

	for _, item := range ref(arr) {
		*item = "some other string"
		fmt.Println(item, arr)
	}
}

I won't encourage to use this. But if you really want to iterate over items by references then you can make a new slice of refs (not best for space complexity) and loop over that.

But with that wherever you are assigning new value to item you'll have to dereference the pointer and use it (that is what makes it bad in my opinion). So yes I won't use this solution.

And also it works only for array of strings. You have to make new ref function for other types :(

Solution 6 - Pointers

It's been said in the comments already, but for those looking for answers right away, here's how you can achieve expected result by using a slice of pointers and by making the least changes to the original code.

package main

import "fmt"

type MyType struct {
    field string
}

func main() {
    // Slice of pointers instead of slice of type
    var array [10]*MyType

    // Initialize array manually
    for idx := range array {
	    array[idx] = &MyType{}
    }

    for _, e := range array {
	    e.field = "foo"
    }

    for _, e := range array {
	    fmt.Println(e.field)
	    fmt.Println("--")
    }

}

Here it is in playground

Solution 7 - Pointers

package main

import "fmt"

type MyType struct {
	field string
}

func main() {
	var array [10]MyType

	for index := range array {
		array[index].field = "foo"
	}

	for _, e := range array {
		fmt.Println(e.field)
		fmt.Println("--")
	}
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionEpitouilleView Question on Stackoverflow
Solution 1 - PointersMushinNoShinView Answer on Stackoverflow
Solution 2 - PointersSam LeeView Answer on Stackoverflow
Solution 3 - PointersGrant ZvolskyView Answer on Stackoverflow
Solution 4 - PointersMuhammad Fauzan AdyView Answer on Stackoverflow
Solution 5 - PointersMutexView Answer on Stackoverflow
Solution 6 - PointersJairo LozanoView Answer on Stackoverflow
Solution 7 - PointersjukayView Answer on Stackoverflow