美文网首页Go语言实践GolangGo
for 循环中取地址引发的错误

for 循环中取地址引发的错误

作者: DJN_ | 来源:发表于2019-07-30 17:30 被阅读3次

    for a,b := range c 遍历中, a 和 b 在内存中只会存在一份,即之后每次循环时遍历到的数据都是以值覆盖的方式赋给 a 和 b,a,b 的内存地址始终不变。

    以下是错误代码示例:

        p := []s2.Rect{}
        var rs []*s2.Rect
        for _, r := range p.Rect {
            rs = append(rs, &r)
        }
    

    因为 r 只会分配一次,因此 &r 始终都指向同一个内存地址,即 rs 切片中的指针对象都指向同一个地址,那么在读取 rs 时都会读到同一个值,for 循环最后一次赋给 r 的值。

    实际开发中这样的情况并不常见,如果将上面的错误代码改成如下两种方式就不会出错:

        p := []s2.Rect{}
        var rs []*s2.Rect
        for _, r := range p.Rect {
            // The for-range only allocate r var once, so &r will point to the same instance within this for statement,
            // make a copy of r then append &c to rs instead of using &r directly.
            c := r
            rs = append(rs, &c)
        }
    

    c := r 会进行值拷贝,c 是一个全新的对象,但值与此时的 r 相同。

        p := []*s2.Rect{}
        var rs []*s2.Rect
        for _, r := range p.Rect {
            rs = append(rs, c)
        }
    

    这个 for-range 中 r 是指针对象,r 始终是同一个对象,但其值是地址,rs = append(rs, c)进行值(地址)拷贝。

    总而言之,在 for a,b := range c 遍历中,要注意 &a &b 这样的操作,对 a 或 b 进行取地址时取到的值(地址)始终相同,可能引发错误。

    相关文章

      网友评论

        本文标题:for 循环中取地址引发的错误

        本文链接:https://www.haomeiwen.com/subject/idkirctx.html