Golang,仅附加最后一个元素

Dfr:

这是示例代码:

package main

import (
    "fmt"
)

type Product struct {
    Id       int64
    Title    string
    AttrVals []string
}

type ProductAttrValView struct {
    Product
    Attr string
}

type ProductAttrVal struct {
    Attr    string
    Product int64
    Value   string
}

func main() {
    p := Product{Id: 1, Title: "test", AttrVals: []string{}}
    var prod *Product
    prodViews := []ProductAttrValView{
        ProductAttrValView{ Product: p, Attr: "text1" },
        ProductAttrValView{ Product: p, Attr: "text2" },
        ProductAttrValView{ Product: p, Attr: "text3" },
        ProductAttrValView{ Product: p, Attr: "text4" },
    }

    // collapse join View to Product with Attrs
    for _, pview := range prodViews {
        if prod == nil {
            prod = &pview.Product
            prod.AttrVals = make([]string, 0, len(prodViews))
        }
        if pview.Attr != "" {
            fmt.Printf("appending '%s' to %p\n", pview.Attr, prod) // output for debug
            prod.AttrVals = append(prod.AttrVals, pview.Attr)
        }
    }
    fmt.Printf("%+v\n", prod) // output for debug

}

http://play.golang.org/p/949w5tYjcH

在这里,我从ProductAttrValViewstruct中的DB返回了一些数据,并希望将其放到Productstruct中并填充Product.AttrVals

它打印:

&{Id:1标题:test AttrVals:[text4]}

虽然我期望这样:

&{Id:1标题:test属性:[text1 text2 text3 text4]}

因此,所有文本都应附加,但由于某种原因,只有最后一个元素留在Attrs切片中。

吉姆:

您正在for-range循环中重新使用变量,并且每次迭代都会修改该变量的值。您可以使用技巧在每次迭代中创建一个新值:

pview := pview

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

您还以4的长度初始化切片,但使用append另一个值(忽略前4个)。您可能打算设置切片的容量而不是长度:

prod.AttrVals = make([]string, 0, len(prodViews))

由于的prod每次迭代都在变化,因此,如果您专门初​​始化该prod值,而不是分配的地址,则代码将减少很多混乱&pview.Product

prod = &Product{AttrVals: make([]string, 0, len(prodViews))}

[时间线]

  1. 您创建一个p包含初始化的[] string 的单个产品
  2. p将分配给所有prodViews我们要迭代的对象。
  3. 在循环的第一次迭代中,您分配*prod了该初始p值,然后更改AttrVals为新[]string的长度4。这不会更改原始值p
  4. pview.Attr被附加到prod.AttrVals,使其长度为5,并创建一个新的基础数组。并未反映在的值中p
  5. 在随后的迭代中,pview将使用中的下一个值覆盖prodViews这也覆盖了值prod,因为它指向该pview.Product值。这意味着prod.AttrVals现在与原始版本相同p
  6. pview.Attr被附加到长度为0的切片上,并且基础数组被替换为更大的容量,因此pview.Attr仍然不包含在原始数组中p
  7. pview再次用包含原始p的下一个值覆盖,并AttrVals使用一个空数组长度设置回0。
  8. 循环继续进行,直到打印出最终的单个值。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章