Parcours
/
Go
Go
/
Programme
/
Fonctions
Fo

Fonctions en Go

1 exercice

À propos de Fonctions

Une fonction permet de regrouper du code dans une unité réutilisable. Elle se compose du mot-clé func, du nom de la fonction et d'une liste, séparée par des virgules, de zéro ou plusieurs paramètres et types entre parenthèses.

Paramètres de fonction

Tous les paramètres doivent avoir un type explicite ; il n'y a pas d'inférence de type pour les paramètres. Les paramètres n'ont pas de valeur par défaut, ils sont donc tous obligatoires.

import "fmt"

// No parameters
func PrintHello() {
    fmt.Println("Hello")
}

// One parameter
func PrintHelloName(name string) {
  fmt.Println("Hello " + name)
}

Les paramètres de même type peuvent être déclarés ensemble, suivis d'une seule déclaration de type.

import "fmt"

func PrintGreetingName(greeting, name string) {
  fmt.Println(greeting + " " + name)
}

Paramètres et arguments

Voyons rapidement deux termes que l'on confond souvent : parameters et arguments. Les paramètres d'une fonction sont les noms définis dans la signature de la fonction, comme greeting et name dans la fonction PrintGreetingName ci-dessus. Les arguments d'une fonction sont les valeurs concrètes transmises aux paramètres de la fonction au moment où on l'appelle. Par exemple, dans l'exemple ci-dessous, "Hello" et "Katrina" sont les arguments passés aux paramètres greeting et name :

PrintGreetingName("Hello", "Katrina")

Valeurs de retour

Les paramètres de la fonction sont suivis de zéro ou plusieurs valeurs de retour, qui doivent elles aussi avoir un type explicite. Une valeur de retour unique s'écrit sans parenthèses, plusieurs valeurs de retour sont mises entre parenthèses. Les valeurs sont renvoyées au code appelant depuis les fonctions grâce au mot-clé return. Une fonction peut contenir plusieurs instructions return. L'exécution de la fonction s'arrête dès qu'elle atteint l'une de ces instructions return. Si une fonction doit renvoyer plusieurs valeurs, elles sont séparées par des virgules. Tu trouveras plus d'informations sur l'usage idiomatique des valeurs de retour multiples dans le concept associé.

func Hello(name string) string {
  return "Hello " + name
}

func HelloAndGoodbye(name string) (string, string) {
  return "Hello " + name, "Goodbye " + name
}

Appeler des fonctions

Pour appeler une fonction, on écrit son nom et on passe des arguments pour chacun de ses paramètres, entre parenthèses.

import "fmt"

// No parameters, no return value
func PrintHello() {
    fmt.Println("Hello")
}
// Called like this:
PrintHello()

// One parameter, one return value
func Hello(name string) string {
  return "Hello " + name
}
// Called like this:
greeting := Hello("Dave")

// Multiple parameters, multiple return values
func SumAndMultiply(a, b int) (int, int) {
    return a+b, a*b
}
// Called like this:
aplusb, atimesb := SumAndMultiply(a, b)

Valeurs de retour nommées et return nu

Tout comme les paramètres, les valeurs de retour peuvent être nommées, de façon facultative. Si tu utilises des valeurs de retour nommées, une instruction return sans arguments renverra ces valeurs. C'est ce qu'on appelle un return « nu ».

func SumAndMultiplyThenMinus(a, b, c int) (sum, mult int) {
    sum, mult = a+b, a*b
    sum -= c
    mult -= c
    return
}

Passage par valeur et passage par référence

Il est également important de clarifier les notions de passage par valeur et de passage par référence.

Commençons par le passage par valeur. Dans l'exemple ci-dessous, quand on passe la variable val à la fonction MultiplyByTwo, c'est une copie de val qui est transmise. C'est pourquoi newVal contient la valeur mise à jour 4, alors que la variable d'origine val vaut toujours 2. En coulisses, Go fait en réalité une copie de la valeur d'origine, de sorte que seule cette copie, autrement dit v, est modifiée par la fonction.

val := 2
func MultiplyByTwo(v int) int {
    v = v * 2
    return v
}
newVal := MultiplyByTwo(val)
// newval is 4, val is still 2 because only a copy of its value was passed into the function

À strictement parler, en Go, tous les arguments sont passés par valeur, c'est-à-dire qu'une copie est faite de la valeur ou des données fournies à la fonction. Mais si tu ne veux pas copier les données transmises à une fonction et que tu veux modifier ces données à l'intérieur de la fonction, tu dois alors utiliser des pointers comme arguments, c'est-à-dire passer par référence.

Pointeurs

On utilise un pointer pour réaliser un passage par référence. En passant des arguments de type pointer à une fonction, on peut modifier les données sous-jacentes transmises à la fonction au lieu de travailler uniquement sur une copie de ces données.

Pour l'instant, il suffit de savoir que les types pointeur se reconnaissent au * placé devant le type dans la signature de la fonction.

func HandlePointers(x, y *int) {
    // Some logic to handle integer values referenced by pointers x and y
}

Si le concept de pointer te semble confus, pas de panique. Une section dédiée plus loin dans le programme t'aidera à maîtriser les pointeurs.

Exceptions

Note que les slices et les maps font exception à la règle mentionnée ci-dessus. Quand on passe un slice ou une map en argument à une fonction, ils sont traités comme des types pointeur, même s'il n'y a pas de * explicite dans le type. Cela signifie que si on passe un slice ou une map à une fonction et qu'on modifie ses données sous-jacentes, les changements se répercutent sur le slice ou la map d'origine.

D'autres types de fonctions

En Go, les fonctions sont considérées comme des citoyens de première classe, ce qui les rend très puissantes. Il existe un certain nombre d'autres concepts autour des fonctions, comme les méthodes et les fonctions anonymes, que tu découvriras plus tard dans ton apprentissage.

Modifie via GitHub Le lien s'ouvre dans une nouvelle fenêtre ou un nouvel onglet

Apprends Fonctions