简体   繁体   English

Go指针 - 通过指针将值附加到切片

[英]Go Pointers - append values to slice via pointer

I have a struct ProductData and its instance p which has a slice attribute : 我有一个结构ProductData及其实例p,它有一个slice属性:

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

I want to set TopAttributes as follows 我想设置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)
}

But this does not seem to work. 但这似乎不起作用。

However, there is another way which works fine when I define a method as: 但是,当我将方法定义为:时,还有另一种方法可以正常工作:

   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)
}

I want to find out why it is not working. 我想找出它为什么不起作用。 There were no errors in my code, but the data coming was empty. 我的代码中没有错误,但数据是空的。 I am trying to do this to make it a generic function as I have another BottomAttributes which has to be set the same way. 我试图这样做使它成为一个泛型函数,因为我有另一个BottomAttributes必须以相同的方式设置。

append returns a reference to the appended-to slice. append返回对附加切片的引用。 This is because it could point to a new location in memory if it needed to be resized. 这是因为如果需要调整大小,它可以指向内存中的新位置。

In your first example, you are updating the variable passed to your setAttribute function, but that's it. 在第一个示例中,您正在更新传递给setAttribute函数的变量,但就是这样。 The only reference is lost when that function exits. 当该函数退出时,唯一的引用将丢失。

It works in the second example because that variable lives in your struct, and is thus updated. 它适用于第二个示例,因为该变量存在于您的结构中,因此更新。

You can fix the first version by using a pointer: 您可以使用指针修复第一个版本:

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)
}

You are trying to append a map value which is used as a function parameter, so it has a local scope, accessible only within the function. 您正在尝试附加用作函数参数的map值,因此它具有本地范围,只能在函数内访问。 Because this is referenced by value and not by pointer address, it's access is restricted only to it's local scope. 因为它是由值引用而不是由指针地址引用,所以它的访问仅限于它的本地范围。

Map types are reference types, like pointers or slices, and so the value of parameter p is nil; 映射类型是引用类型,如指针或切片,因此参数p值为nil; it doesn't point to an initialized map. 它没有指向初始化的地图。

To point it to a map you have to access trough it's pointer: 要将其指向地图,您必须通过它的指针访问:

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)
}

Shortly, though we can use slice to modify the source data, but for slice itself, when as an argument for function, it just pass a copy into the function. 不过,虽然我们可以使用slice来修改源数据,但对于slice本身,当作为函数的参数时,它只是将副本传递给函数。 so, your code like this 所以,你的代码是这样的

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM