英文:
Range references instead values
问题
我看到range返回键和值的“副本”。有没有办法让range返回项目的地址呢?例如:
package main
import "fmt"
type MyType struct {
field string
}
func main() {
var array [10]*MyType
for _, e := range array {
e = &MyType{field: "foo"}
}
for _, e := range array {
fmt.Println(e.field)
fmt.Println("--")
}
}
在这个例子中,"field"没有被修改,因为range发送的是field的副本。我是否必须使用索引,还是有其他方法可以修改值?
英文:
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?
答案1
得分: 192
简短而直接的答案是:不要使用值,而是使用数组索引。
所以上述代码变为:
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("--")
}
}
英文:
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("--")
}
}
答案2
得分: 11
将@Dave C和@Sam Toliman的评论合并起来
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
英文:
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("--")
}
}
答案3
得分: 9
Go的range
只支持按值赋值。没有&range
,因为它解决的问题太简单了。
可以通过以下方式实现所需的效果:
for i := range array {
e := &array[i]
e.field = "foo"
}
英文:
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"
}
答案4
得分: 2
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("--")
}
}
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("--")
}
}
这是一个Go语言的代码示例,它定义了一个名为MyType
的结构体,其中包含一个名为field
的字符串字段。在main
函数中,创建了一个长度为10的array
数组,然后使用循环为每个元素的field
字段赋值为"foo"。最后,使用循环打印出每个元素的field
字段的值,并在每个值之后打印"--"。
英文:
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("--")
}
}
答案5
得分: 1
如果您想访问v的引用值(例如for i, v := range arr
)以更新数组中对象的值,有三种有希望(相对简单)的解决方法:
-
如第一个答案所建议的,从数组内部更新arr[i]而不是v(例如
arr[i] = "Hello"
)。 -
仅当您的数组包含一组需要更新但不替换的结构体时,在数组内将v设置为arr[i],然后通过v更新属性(例如
v := arr[i]; v.thingSheSays = "Hello"
)。 -
或者,我最喜欢的方法是定义一个包含对象地址的数组。然后在for循环内使用指针访问对象。可以这样做:
输入:
a, b, c := "A", "B", "C"
arr := []*string{&a, &b, &c}
fmt.Println("- Arr Value Updates:")
for i, v := range arr {
*v = "Hello"
fmt.Println("v's value: " + *v)
fmt.Println("arr[i]'s value: " + *arr[i])
}
输出:
- Arr Value Updates:
v's value: Hello
arr[i]'s value: Hello
v's value: Hello
arr[i]'s value: Hello
v's value: Hello
arr[i]'s value: Hello
希望这能帮助到某些人,因为作为Go语言的新手,这最初让我感到困惑。欢迎分享您自己避免此问题的方法!
英文:
If you would like to access v's reference value (as in for i, v := range arr
) to update the value of the object in the array, there are three promising (relatively simple) workarounds:
-
Like the first answer suggested, update arr[i] instead of v from within the array (e.g.,
arr[i] = "Hello"
) -
ONLY IF your array contains a set of structs you need to update but not replace in the array's assignment, set v to arr[i] within your array and then update properties through v (e.g.,
v := arr[i]; v.thingSheSays = "Hello";
) -
Or, my favorite—define an array containing the object addresses. Then access the objects using a pointer from within the for-loop. Do this like so:
Input:
a, b, c := "A", "B", "C"
arr := []*string{&a, &b, &c}
fmt.Println("- Arr Value Updates:")
for i, v := range arr {
*v = "Hello"
fmt.Println("v's value: " + *v)
fmt.Println("arr[i]'s value: " + *arr[i])
}
Output:
- Arr Value Updates:
v's value: Hello
arr[i]'s value: Hello
v's value: Hello
arr[i]'s value: Hello
v's value: Hello
arr[i]'s value: Hello
Hope this was able to help someone, as it initially stumped me as a newbie to golang for-loops. Feel free to share your own methods for avoiding this issue!
答案6
得分: 0
类型 arrType []string
类型 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)
}
}
我不鼓励使用这种方法。但是如果你真的想要通过引用迭代项目,你可以创建一个新的引用切片(空间复杂度不是最佳),然后在该切片上进行循环。
但是在你给item赋新值时,你必须解引用指针并使用它(这就是我认为它不好的地方)。
所以是的,我不会使用这个解决方案。
而且它只适用于字符串数组。你必须为其他类型创建新的ref
函数
英文:
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
答案7
得分: -1
已经在评论中提到了,但对于那些希望立即获得答案的人来说,以下是如何通过使用指针切片并对原始代码进行最少更改来实现预期结果的方法。
package main
import "fmt"
type MyType struct {
field string
}
func main() {
// 使用指针切片代替类型切片
var array [10]*MyType
// 手动初始化数组
for idx := range array {
array[idx] = &MyType{}
}
for _, e := range array {
e.field = "foo"
}
for _, e := range array {
fmt.Println(e.field)
fmt.Println("--")
}
}
在playground中可以查看。
英文:
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
答案8
得分: -2
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("--")
}
}
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("--")
}
}
英文:
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("--")
}
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论