1 Notions de base des fonctions

En programmation, une fonction est un morceau de code qui accomplit une tâche spécifique et peut comporter des paramètres d'entrée et des valeurs de retour. En langage Go, les fonctions sont largement utilisées pour organiser et réutiliser du code. Utiliser les fonctions de manière efficace peut rendre le code plus concis, très lisible et facile à maintenir.

Les fonctions sont un composant de base du langage Go, et comprendre comment déclarer et définir des fonctions est essentiel pour écrire un code efficace et lisible.

2 Définition des fonctions

2.1 Déclaration de fonctions

En langage Go, la forme générale de la déclaration de fonction est la suivante :

func nomFonction(paramètres) typeRetour {
    // Corps de la fonction
}

Analysons ces composants :

  1. Le mot-clé func est utilisé pour déclarer une fonction.
  2. nomFonction est le nom de la fonction, suivant les conventions de nommage du langage Go. Une fonction commençant par une lettre majuscule est exportable, c'est-à-dire qu'elle est visible en dehors du package ; une fonction commençant par une lettre minuscule n'est pas exportable et ne peut être utilisée que dans le même package.
  3. paramètres est la liste des paramètres reçus par la fonction, séparés par des virgules. Le type de chaque paramètre doit être spécifié, et si plusieurs paramètres ont le même type, le type peut être spécifié une seule fois.
  4. typeRetour est le type de la valeur retournée par la fonction. Si la fonction ne renvoie pas de valeur, cette partie peut être omise. Si la fonction renvoie plusieurs valeurs, elles doivent être encloses entre parenthèses.

Par exemple, nous pouvons déclarer une fonction simple pour calculer la somme de deux entiers :

func Ajouter(a int, b int) int {
    return a + b
}

Dans cet exemple, le nom de la fonction est Ajouter, elle prend deux paramètres de type int (a et b), et elle renvoie leur somme avec le type de retour int.

2.2 Liste de paramètres

La liste de paramètres définit les paramètres que la fonction accepte et le type de chaque paramètre. Les paramètres sont une sorte spéciale de variable utilisée pour transmettre des données à une fonction.

func Saluer(nom string, age int) {
    fmt.Printf("Bonjour, %s ! Tu as %d ans.\n", nom, age)
}

Dans cette fonction Saluer, nom et age sont des paramètres. Le type de nom est string, et le type de age est int. Lors de l'appel de cette fonction, des valeurs réelles doivent être fournies pour ces paramètres.

2.3 Types de retour

Les fonctions peuvent renvoyer des résultats calculés, et le type de retour définit le type de données de la valeur retournée par la fonction. Les fonctions peuvent ne pas avoir de valeur de retour, ou elles peuvent avoir une ou plusieurs valeurs de retour.

Si une fonction a plusieurs valeurs de retour, leurs types doivent être encloses entre parenthèses lors de la déclaration :

func Diviser(dividende, diviseur float64) (float64, error) {
    if diviseur == 0 {
        return 0, errors.New("impossible de diviser par zéro")
    }
    return dividende / diviseur, nil
}

La fonction Diviser renvoie ici deux valeurs : le quotient et un message d'erreur. Si le diviseur est zéro, une erreur est renvoyée.

2.4 Paramètres variadiques

En Go, lorsque nous ne sommes pas sûrs du nombre de paramètres que l'appelant passera lors de la définition d'une fonction, nous pouvons utiliser des paramètres variadiques. Les paramètres variadiques sont indiqués par une ellipse ..., ce qui signifie que la fonction peut accepter un nombre quelconque de paramètres. Cela est très utile lors du traitement d'une quantité incertaine de données ou lors de la mise en œuvre de certains types de fonctions tels que le formatage, la synthèse ou les fonctionnalités d'itération.

Scénarios d'application

Les paramètres variables sont couramment utilisés dans les scénarios suivants :

  1. Concaténation de chaînes : telles que les fonctions fmt.Sprintf et strings.Join.
  2. Traitement de tableau/tranche : lors du traitement de tableaux ou tranches de longueurs variables, tels que le calcul de la somme ou la concaténation de plusieurs tranches.
  3. Journalisation et gestion des erreurs : lors de la gestion de plusieurs erreurs ou de l'enregistrement de plusieurs informations de journal, telles que log.Printf ou des fonctions personnalisées de synthèse d'erreurs.
  4. Fonctions d'aide : utilisées dans les API ou les bibliothèques pour fournir aux utilisateurs des façons plus flexibles d'appeler des fonctions.

Utilisation de paramètres variables

Voici un exemple simple d'utilisation de paramètres variables :

// Définir une fonction qui prend un nombre variable de paramètres entiers et renvoie leur somme
func Sum(nums ...int) int {
    total := 0
    for _, num := range nums {
        total += num
    }
    return total
}

func main() {
    // Vous pouvez passer n'importe quel nombre de paramètres
    fmt.Println(Sum(1, 2))          // Sortie : 3
    fmt.Println(Sum(1, 2, 3, 4))    // Sortie : 10
    
    // Vous pouvez également passer une tranche et utiliser les points de suspension après la tranche
    numbers := []int{1, 2, 3, 4, 5}
    fmt.Println(Sum(numbers...))    // Sortie : 15
}

Dans la fonction Sum, nums est une tranche d'entiers qui contient tous les paramètres passés à la fonction Sum. Nous pouvons utiliser une boucle range pour itérer à travers cette tranche et calculer la somme.

Il est à noter que les paramètres variables à l'intérieur de la fonction sont en fait une tranche, donc toutes les opérations liées à la tranche peuvent être utilisées. Lorsque vous devez passer une tranche en tant que paramètre variable à une fonction, ajoutez simplement des points de suspension ... après la tranche.

L'utilisation de paramètres variables peut rendre les appels de fonctions plus flexibles et concis, mais elle aura également un léger impact sur les performances, car l'utilisation de paramètres variables implique la création de tranches et l'allocation de mémoire. Par conséquent, il convient d'être prudent lorsque des exigences strictes en matière de performances sont en place.

Astuce : Une explication détaillée sur les tranches sera fournie dans les chapitres ultérieurs. Si vous avez de l'expérience avec d'autres langages de programmation, vous pouvez temporairement les considérer comme des tableaux.

3 Appels de fonctions

3.1 Appels de fonctions de base

Appeler une fonction signifie exécuter le code de la fonction. En Go, appeler une fonction définie est très simple, il suffit d'utiliser le nom de la fonction et de passer les paramètres appropriés. Par exemple :

resultat := add(3, 4)
fmt.Println(resultat)  // Sortie : 7

Dans cet exemple, la fonction add est appelée et deux entiers sont passés en tant que paramètres, puis le résultat retourné est attribué à la variable resultat.

3.2 Passage de paramètres

Lors du passage de paramètres à une fonction, Go utilise par défaut le passage par valeur, ce qui signifie passer une copie de la valeur du paramètre, et les données d'origine ne seront pas modifiées. Cependant, si vous souhaitez que la fonction modifie des variables externes ou pour des raisons de performances, vous pouvez utiliser le passage par référence, tel que l'utilisation de pointeurs ou le passage de grandes structures.

Voici des exemples de passage par valeur et de passage par référence :

// Exemple de passage par valeur
func double(val int) {
    val *= 2
}

// Exemple de passage par référence
func doublePtr(val *int) {
    *val *= 2
}

func main() {
    valeur := 3
    double(valeur)
    fmt.Println(valeur)  // Renvoie 3, la valeur reste inchangée

    doublePtr(&valeur)
    fmt.Println(valeur)  // Renvoie 6, valeur doublée
}

Dans l'exemple ci-dessus, la fonction double essaie de doubler la val passée, mais elle ne fait que doubler sa copie, laissant la variable originale valeur inchangée. Cependant, la fonction doublePtr change la valeur de la variable d'origine en recevant un pointeur vers une variable entière en tant que paramètre.