Maison  >  Article  >  développement back-end  >  ## Pourquoi la copie d'instances de types Go avec des méthodes de récepteur de pointeur est-elle dangereuse ?

## Pourquoi la copie d'instances de types Go avec des méthodes de récepteur de pointeur est-elle dangereuse ?

Linda Hamilton
Linda Hamiltonoriginal
2024-10-25 10:54:30185parcourir

## Why is Copying Instances of Go Types with Pointer Receiver Methods Dangerous?

Pièges de la copie d'instances avec des méthodes de récepteur de pointeur

En Go, si toutes les méthodes pour un type nommé T ont un type de récepteur de T lui-même (et non *T), la copie d'instances de ce type est considérée comme sûre. En effet, tout appel de méthode opère nécessairement sur une copie, garantissant que la valeur d'origine reste inchangée. Cependant, si une méthode pour T a un récepteur de pointeur, copier des instances de T peut être dangereux.

Explication

Lors de l'appel d'une méthode, la valeur que la méthode est invoquée on est d'abord copié et la copie est transmise en tant que récepteur. Si un type ne possède que des méthodes avec des récepteurs de valeur, cela garantit que les méthodes ne peuvent pas modifier la valeur d'origine, quelles que soient leurs actions. En effet, une copie est toujours utilisée, protégeant l'original des modifications involontaires.

Cependant, si un type possède des méthodes avec des récepteurs de pointeurs, ces méthodes peuvent modifier la valeur pointée d'origine plutôt que sa copie. En effet, la méthode reçoit un pointeur vers la valeur d'origine, lui permettant de modifier les données sous-jacentes.

Exemple

Considérons un wrapper de type Wrapper :

type Wrapper struct {
    v int
    p *int
}

Avec une méthode Set() pour s'assurer que les deux champs contiennent la même valeur :

func (w *Wrapper) Set(v int) {
    w.v = v
    *w.p = v
}

Si nous créons une instance de Wrapper :

a := Wrapper{v: 0, p: new(int)}

Et faisons ensuite un copie (b) de a :

b := a

Après avoir défini a sur 1 à l'aide de Set() :

a.Set(1)

Nous nous attendons à ce que a et b aient leurs champs définis sur 1. Cependant, l'impression de leurs valeurs révèle une autre histoire :

fmt.Printf("a.v=%d, a.p=%d;  b.v=%d, b.p=%d\n", a.v, *a.p, b.v, *b.p)

Sortie :

a.v=1, a.p=1;  b.v=0, b.p=1

La raison de cet écart est que même si le pointeur dans b est copié, il fait toujours référence au même données sous-jacentes comme pointeur dans a. Lorsque Set() modifie la valeur pointée, cela affecte les deux copies de Wrapper. Cependant, le champ non-pointeur v reste distinct entre a et b.

Bonne pratique

Pour éviter ce problème, il est recommandé de s'abstenir de copier des instances de types avec méthodes de récepteur de pointeur. Si travailler avec des valeurs de pointeur est nécessaire, copier le pointeur lui-même (*T) est une alternative viable.

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn