【问题标题】:Go Pointers - append values to slice via pointerGo Pointers - 通过指针将值附加到切片
【发布时间】:2016-10-16 13:09:12
【问题描述】:

我有一个结构 ProductData 和它的实例 p,它有一个 slice 属性:

type ProductInfo struct {
    TopAttributes []map[string]interface{}
}

我想设置TopAttributes如下

func (p *ProductInfo) setAttributeData() {
    key := "key"
    value := "value"
    setAttribute(p.TopAttributes, key, value)
}

func setAttribute(p []map[string]interface{}, key string, value interface{}) {
    val := map[string]interface{}{
        key: value,
    }
    p = append(p, val)
}

但这似乎不起作用。

但是,当我将方法定义为时,还有另一种方法可以正常工作:

   func (p *ProductInfo) setAttributeData() {
    key := "key"
    value := "value"
    p.setAttribute(key, value)
}

func (p *ProductInfo) setAttribute(key string, value interface{}) {
    val := map[string]interface{}{
        key: value,
    }
    p.TopAttributes = append(p.TopAttributes, val)
}

我想知道它为什么不起作用。我的代码没有错误,但传入的数据是空的。 我试图这样做以使其成为通用函数,因为我有另一个必须以相同方式设置的 BottomAttributes。

【问题讨论】:

  • 请给Minimal, Viable, Complete Example. 根据你给我们的代码,这甚至不应该编译。您引用 attrData,您的意思是 attrCode 吗?
  • 我已经给出了所需的代码。

标签: pointers go slice


【解决方案1】:

append 返回对附加到切片的引用。这是因为如果需要调整大小,它可能会指向内存中的新位置。

在您的第一个示例中,您正在更新传递给 setAttribute 函数的变量,仅此而已。当该函数退出时,唯一的引用会丢失。

它在第二个示例中有效,因为该变量存在于您的结构中,因此会被更新。

您可以使用指针修复第一个版本:

func (p *ProductInfo) setAttributeData() {
    key := "key"
    value := "value"
    setAttribute(&p.TopAttributes, key, value)
}

func setAttribute(p *[]map[string]interface{}, key string, value interface{}) {
    val := map[string]interface{}{
        key: value,
    }
    *p = append(*p, val)
}

【讨论】:

  • 我尝试了上述方法,但错过了 *p = append(*p, val) 部分。谢谢,现在可以使用了。
  • 我还有一个问题 - 所有切片和地图都作为参考传递。因此,当我传递 TopAttributes 的引用(这是一个切片)并将值设置为 p = append(p, val) 时,它不应该工作。这也在某种程度上更新了引用。
  • 您正在更新参考。但只有 setAttribute 看到的引用。当您使用指向该“引用”的指针时,您正在更新 setAttributeData 具有的变量。在 C 语言中,它是一个指向指针的指针。
【解决方案2】:

您正在尝试附加一个用作函数参数的map 值,因此它具有本地范围,只能在函数内访问。因为这是通过值而不是指针地址引用的,所以它的访问仅限于它的本地范围。

映射类型是引用类型,如指针或切片,因此参数p 的值为nil;它不指向已初始化的地图。

要将其指向地图,您必须通过它的指针访问:

func (p *ProductInfo) setAttributeData() {
    key := "key"
    value := "value"
    setAttribute(p.TopAttributes, key, value)
}

func setAttribute(p *[]map[string]interface{}, key string, value interface{}) {
    val := map[string]interface{}{
        key: value,
    }
    *p = append(*p, val)
}

【讨论】:

    【解决方案3】:

    简而言之,虽然我们可以使用 slice 来修改源数据,但是对于 slice 本身,当作为函数的参数时,它只是将副本传递给函数。 所以,你的代码是这样的

    func test(i int) {
        i = i + 1
    }
    var a int = 3
    test(a)
    

    【讨论】:

      猜你喜欢
      • 2017-10-03
      • 2017-08-11
      • 2015-10-16
      • 1970-01-01
      • 2016-07-17
      • 1970-01-01
      • 2018-12-05
      • 2017-04-05
      • 2016-12-28
      相关资源
      最近更新 更多