web-dev-qa-db-fra.com

Go Pointers - ajoutez des valeurs à découper via un pointeur

J'ai une struct ProductData et son instance p qui a un attribut slice:

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

Je veux définir TopAttributes comme suit

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

Mais cela ne semble pas fonctionner.

Cependant, il existe un autre moyen qui fonctionne bien lorsque je définis une méthode comme:

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

Je veux savoir pourquoi cela ne fonctionne pas. Il n'y avait aucune erreur dans mon code, mais les données à venir étaient vides. J'essaie de le faire pour en faire une fonction générique car j'ai un autre BottomAttributes qui doit être défini de la même manière.

14
Prateek

append renvoie une référence à la tranche ajoutée. En effet, il pourrait pointer vers un nouvel emplacement en mémoire s'il devait être redimensionné.

Dans votre premier exemple, vous mettez à jour la variable passée à votre fonction setAttribute, mais c'est tout. La seule référence est perdue lorsque cette fonction se termine.

Cela fonctionne dans le deuxième exemple car cette variable réside dans votre structure et est donc mise à jour.

Vous pouvez corriger la première version en utilisant un pointeur:

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)
}
16
Kevin M Granger

Vous essayez d'ajouter une valeur map qui est utilisée comme paramètre de fonction, afin qu'elle ait une portée locale, accessible uniquement dans la fonction. Parce que cela est référencé par valeur et non par adresse de pointeur, son accès est limité uniquement à sa portée locale.

Les types de carte sont des types de référence, comme des pointeurs ou des tranches, et donc la valeur du paramètre p est nulle; il ne pointe pas vers une carte initialisée.

Pour le pointer vers une carte, vous devez accéder à son pointeur:

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)
}
4
Endre Simo

En bref, bien que nous puissions utiliser la tranche pour modifier les données source, mais pour la tranche elle-même, lorsqu'elle est utilisée comme argument pour la fonction, elle passe simplement une copie dans la fonction. donc, votre code comme celui-ci

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