ProgrammationDéveloppeur Backend

Décrivez comment les fonctions variadiques (fonctions avec un nombre variable d'arguments) sont implémentées en Go. Comment les déclarer correctement, les appeler, et quels pièges peuvent survenir lors du passage de tranches ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse

Les fonctions variadiques en Go permettent de prendre un nombre variable d'arguments d'un type donné grâce à la syntaxe avec trois points .... Par exemple:

func sum(nums ...int) int { total := 0 for _, num := range nums { total += num } return total }

Cette fonction peut être appelée avec n'importe quel nombre d'arguments:

result := sum(1, 2, 3, 4) // 10

Ou transmettre une tranche en utilisant la syntaxe ...:

numbers := []int{1,2,3} result := sum(numbers...) // 6

Subtilités:

  • Les paramètres variadiques sont vus dans la fonction comme une tranche ([]T). Cela signifie que vous pouvez passer une tranche préparée.
  • Ces paramètres doivent toujours être les derniers dans la liste des paramètres de la fonction.
  • Si vous passez une tranche sans ..., la fonction attend un paramètre normal de type []T, et non variadique.

Question piégeuse

Quel résultat donnera le code suivant et pourquoi ?

func printInts(nums ...int) { fmt.Printf("%#v ", nums) } ints := []int{1, 2, 3} printInts(ints)

Beaucoup pensent à tort que ce code se compilera, mais en réalité il provoquera une erreur de compilation:

Erreur : impossible de passer une tranche sans ... à un paramètre variadique.

Correct :

printInts(ints...) // OK

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


Histoire

Dans un grand projet, la fonction de journalisation était décrite comme func Log(msgs ...string). Lors du passage d'une tranche de chaînes préparée, on appelait simplement Log(strings), ce qui produisait une sortie de journal incorrecte ou un panic pendant l'exécution. La raison en était l'absence de ..., donc la fonction interprétait un argument de type []string, et non des chaînes individuelles.


Histoire

Dans une des fonctions utilitaires, il était nécessaire de traiter des paramètres, parmi lesquels se trouvait une tranche, et d'y ajouter davantage d'éléments à l'intérieur. On pensait que ... créait une copie de la tranche, et non passait une référence — mais à l'intérieur de la fonction, la tranche était modifiée, ce qui affectait de manière inattendue la partie appelante, surtout si la tranche d'origine était un tampon réutilisable.


Histoire

Un développeur a réalisé des fonctions d'agrégation en utilisant un paramètre variadique, mais un des collègues a mal utilisé la syntaxe d'appel via un casting : sum(interface{}([]int)), ce qui entraînait des erreurs d'exécution implicites, alors qu'il aurait été correct d'utiliser explicitement sum(slice...). L'ignorance des nuances a causé des bogues non évidents lors de refactorisations massives.