登录
首页 >  Golang >  Go问答

出现意外行为的情况下如何正确使用Go的range语法

来源:stackoverflow

时间:2024-03-22 21:54:31 103浏览 收藏

在 Go 中使用 range 遍历结构数组时,其行为可能与预期不符。当遍历一个切片时,每个元素的副本会被复制到范围索引中。但是,对于内部切片,不会进行深层复制。这意味着对内部切片元素的修改会影响原始切片,而对外部切片元素的修改则不会。

问题内容

可能只是因为我是 go 新手,但在结构数组上使用范围语法的行为并不符合我的预期。我假设数组项被复制到范围索引,但副本不是深层副本......所以以下内容有点奇怪。此行为是否记录在某处

package main

import "fmt"

type Inner struct {
        x, y int
}
type Attr struct {
        a      int
        inside []Inner
}

var item = []Attr{
        {a: 1, inside: []Inner{{2, 3}, {3, 4}}},
        {a: 2, inside: []Inner{{3, 4}, {1, 2}}},
}

func main() {
        fmt.Println(item) 
        for _,i := range item {
                // A: The following has no impact on item[].a
                i.a = 111
                // B: But this does ... why?
                i.inside[0].x = 111
        }
        fmt.Println(item) 
        for j,_  := range item {
                item[j].a = 333
                item[j].inside[0].x = 333
        }
        fmt.Println(item)
}

解决方案


在循环for _, i := range item中,每个i都是对应切片元素的副本。假设你写:

i := item[0]
i.a = 111

这不会更改切片的原始元素,而只会更改其副本。然而在:

i.inside[0].x = 111

inside 是一个切片,即仅引用底层数组的薄包装器,在赋值时不会复制该数组。因此,使用 i.inside 处理与 items[0].inside 相同的切片。

More about slices internals

好了,本文到此结束,带大家了解了《出现意外行为的情况下如何正确使用Go的range语法》,希望本文对你有所帮助!关注golang学习网公众号,给大家分享更多Golang知识!

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>