ProgrammationDéveloppeur Go

Comment fonctionne la fonction copy() en Go lors de la copie de tableaux ? Quelles sont les particularités, les limitations et les effets inattendus liés à l'augmentation de la longueur et de la capacité des tableaux ? Que se passe-t-il lorsque les tableaux se chevauchent et que l'on tente de les copier de manière superposée ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

La fonction copy(dst, src []T) int copie les éléments de src vers dst.

  • Elle retourne le nombre d'éléments copiés : min(len(dst), len(src)).
  • La copie se fait par index : les éléments src[i] sont copiés vers dst[i].
  • Ce sont les contenus (valeurs) qui sont copiés, pas des pointeurs vers des objets.

Subtilités et limitations :

  • Si les tableaux se chevauchent (par exemple, l'un est un sous-tableau de l'autre), la copie se fait comme si un extrait des valeurs d'origine était d'abord extrait avant d'être copié (aucune garantie de validité en cas de chevauchement).
  • Si dst a une longueur plus courte que src, seuls les données autorisées par la longueur de dst seront copiées.
  • Si dst a une capacité supérieure à sa longueur, la fonction copy étend-elle le tableau ? — Non, seule len(dst) est considérée comme la cible. Pour l'extension, utilisez prepend d'abord.

Exemple :

a := []int{1,2,3,4,5} b := make([]int, 3) copy(b, a) // b: [1 2 3]

Chevauchement :

x := []int{1,2,3,4} copy(x[1:], x[:3]) // [1 1 2 3]

Question piégeuse

La fonction copy() peut-elle être utilisée pour augmenter la longueur d'un tableau ? Que se passe-t-il si l'on passe à copy un tableau de destination de plus grande capacité mais de plus petite longueur que nécessaire ?

Réponse :

  • copy() ne modifie pas la longueur du tableau cible — elle copie uniquement jusqu'à len(dst)
  • Si dst possède une capacité supérieure à sa longueur, étendez-le d'abord avec dst = dst[:newLen], puis utilisez copy()

Exemple, souvent peu évident :

a := []int{1,2,3} b := make([]int, 0, 5) copy(b, a) // b restera vide, car len(b)==0 b = b[:len(a)] copy(b, a) // maintenant b: [1,2,3]

Exemples d'erreurs réelles dues à l'ignorance des subtilités du sujet


Histoire

Dans le projet, des données ont été copiées d'un tableau à un autre, pensant que copy élargirait automatiquement la longueur de dst à celle nécessaire. Cela ne s'est pas produit, les éléments n'ont pas été copiés, et par conséquent, des données nulles étaient renvoyées dans la réponse API. L'erreur n'a été trouvée qu'après avoir comparé les longueurs des tableaux — le problème était que dst avait une grande capacité, mais une longueur égale à 0.


Histoire

Une partie du microservice fonctionnait avec des tableaux qui se chevauchent, pensant à tort que copy fonctionnerait toujours correctement. En conséquence, la copie vers l'avant détruisait les données d'origine, et des bugs "invisibles" apparaissaient lors du travail avec les buffers. Cela a été résolu en utilisant un buffer temporaire (copy(tmp, src), puis copy(dst, tmp)).


Histoire

Un ingénieur optimisait un tableau en utilisant copy pour trier des données entre des tableaux. Il s'attendait à ce que copy ajuste la longueur de dst. Il s'est avéré que cela ne se produisait pas, et des paniques et des dépassements de valeurs significatives ont commencé à apparaître — il avait oublié d'ajuster correctement la longueur du tableau avant la copie.