Aller au contenu

Apprendre le GO

Mise à jour :

Go

Go, aussi appelé Golang, est devenu une alternative de choix à des langages comme Python, notamment lorsqu’il s’agit des programmes complexes. Pourquoi ? Go combine simplicité et performances grâce à son design minimaliste et sa compilation directe en binaire. Là où Python brille par sa flexibilité, Go excelle par sa rapidité d’exécution et sa capacité à gérer efficacement la concurrence. Si vous avez déjà ressenti des lenteurs avec Python ou affronté ses subtilités dans des environnements distribués, Go pourrait bien devenir votre nouvel allié.

Dans ce guide, on va apprendre les bases pour que vous puissiez écrire vos premiers scripts Go en un rien de temps.

Un peu d’Histoire

Le langage Go a été conçu pour répondre aux besoins de Google en matière de développement de systèmes et de logiciels à grande échelle. Sa création remonte à 2007, sous l’impulsion de trois ingénieurs de renom, Robert Griesemer, Rob Pike et Ken Thompson, tous salariés chez Google. Leur objectif principal était de surmonter les défis posés par les langages existants en termes de performance, d’évolutivité et de facilité de maintenance.

Lors de sa conception, les créateurs de Go ont mis un point d’honneur à souligner la simplicité et l’efficacité en s’inspirant des atouts des langages C et C++, tout en intégrant des avancées innovantes pour la gestion de la concurrence et en corrigeant certains de leurs inconvénients. En novembre 2009, Go a été dévoilé au public comme un projet open source, permettant à des développeurs du monde entier de contribuer à son évolution, de tester ses capacités et de proposer des améliorations précieuses. La version 1.0 de Go a Go a été dévoilé au public comme un projet open source, permettant à des l’introduction d’une API stable. Depuis ce lancement, le langage a connu une évolution constante avec des mises à jour régulières, tout en garantissant la compatibilité en arrière. Au fil du temps, Go a gagné en popularité, notamment auprès des grandes entreprises technologiques. Sa capacité à gérer aisément des processus concurrentiels tout en offrant des performances exceptionnelles a séduit de nombreux développeurs et architectes logiciels.

Au fil du temps, Go a gagné en popularité, notamment dynamique qui enrichit continuellement le langage avec des bibliothèques, des outils et des frameworks, facilitant ainsi son adoption et son utilisation dans une variété de projets. écosystème solide s’est construit autour de Go, porté par une communauté dynamique qui enrichit continuellement le langage avec des bibliothèques, des outils et des frameworks, facilitant ainsi son adoption et son utilisation dans

Installation de Go : Étapes simples et rapides

  1. Téléchargez l’installateur ou l’archive Rendez-vous sur la page officielle de téléchargement de Go et choisissez la version correspondant à votre système d’exploitation.

  2. Installez Go sur votre système

    • Windows : Téléchargez le fichier .msi, exécutez-le, et suivez les étapes de l’assistant d’installation. L’installateur configure automatiquement le chemin d’accès C:\Go\bin.
    • Linux/macOS : Téléchargez l’archive .tar.gz, puis exécutez les commandes suivantes dans le terminal :
Terminal window
sudo tar -C /usr/local -xzf go1.xx.x.linux-amd64.tar.gz

(Remplacez go1.xx.x.linux-amd64.tar.gz par le nom du fichier téléchargé.)

  1. Les variables d’environnement importantes

Pour que Go fonctionne correctement, il est essentiel de configurer certaines variables d’environnement. Voici les plus importantes :

  • GOPATH : Indique le répertoire où sont stockés vos projets et dépendances. Par défaut, il est défini dans votre répertoire utilisateur ($HOME/go sur Linux/macOS ou %USERPROFILE%\go sur Windows). Si vous souhaitez personnaliser ce chemin, ajoutez dans votre fichier de configuration shell (~/.bashrc, ~/.zshrc, ou autre) :

    Terminal window
    export GOPATH=$HOME/my-go-projects
  • GOROOT : Indique où Go est installé. En général, vous n’avez pas besoin de modifier cette variable, car elle est automatiquement définie après l’installation. Par exemple, sur Linux/macOS, elle est définie à /usr/local/go.

  • PATH : Ajoutez le chemin du dossier contenant les binaires de Go pour pouvoir utiliser les commandes comme go build ou go run. Par exemple :

    Terminal window
    export PATH=$PATH:/usr/local/go/bin:$GOPATH/bin

Votre première application Go

Maintenant que vous avez installé Go, vous pouvez créer votre première application Go.

Pour créer un projet Go, vous devez créer un répertoire dans lequel vous stockerez vos fichiers de code. Par exemple, si vous souhaitez créer un projet nommé my-first-go-project, vous pouvez créer un répertoire nommé my-first-go-project dans votre répertoire utilisateur.

Créer un fichier Go

Vous pouvez créer un fichier Go en utilisant n’importe quel éditeur de texte. Par exemple, si vous utilisez Visual Studio Code, vous pouvez créer un fichier nommé main.go dans le répertoire my-first-go-project.

Dans votre fichier main.go, ajoutez le code suivant :

package main
import "fmt"
func main() {
fmt.Println("Hello, world!")
}

Tout commence par une déclaration de package. En Go, chaque fichier appartient à un package, une sorte de regroupement logique du code. Si votre programme doit s’exécuter (et non juste fournir une bibliothèque), il doit obligatoirement appartenir au package main. C’est ici que tout démarre.

Ajouter des fonctionnalités avec les imports

Vous avez le squelette (main), mais il faut lui donner du muscle. C’est là qu’interviennent les packages. Go possède une bibliothèque standard robuste qui vous évite de réinventer la roue. Par exemple, si vous voulez afficher un message dans le terminal, vous importez le package fmt :

import "fmt"

Imaginez un instant que vous deviez écrire vous-même un module d’affichage. En Go, pas besoin : tout est prêt à l’emploi.

Et si votre programme a besoin de plusieurs fonctionnalités ? Pas de souci, regroupez vos imports dans un bloc :

import (
"fmt"
"os"
)

Cela rend le tout plus propre, et Go adore la propreté. Après tout, l’ordre des choses, c’est la base, non ?

La fonction main est le point d’entrée de tout programme Go. Imaginez-la comme la porte d’entrée d’une maison : sans elle, impossible de visiter l’intérieur. Voici un exemple simple :

func main() {
fmt.Println("Hello, Go!")
}

Ce bout de code fait une seule chose : afficher “Hello, Go!” dans le terminal. C’est minimaliste, mais incroyablement puissant. Pourquoi ? Parce que tout, absolument tout, part de cette fonction.

Et si on complexifie un peu ? Supposons que vous voulez demander le nom de l’utilisateur et afficher un message personnalisé. Avec Go, c’est tout aussi simple :

func main() {
var name string
fmt.Print("Entrez votre nom : ")
fmt.Scanln(&name)
fmt.Printf("Bonjour, %s ! Bienvenue dans Go.\n", name)
}

Là, on commence à voir la magie de Go : un code clair, lisible, mais qui fait exactement ce qu’on attend de lui. Et tout ça dans le package main.

Organiser un programme plus complexe

Au fur et à mesure que votre code grandit, il devient essentiel de l’organiser en plusieurs fichiers ou packages. Imaginez un programme qui aurait tout dans un seul fichier… ce serait comme essayer de ranger toute une maison dans une seule pièce.

Voici un exemple d’organisation typique :

  • Dossier du projet :

    myproject/
    ├── main.go
    ├── utils/
    └── helper.go

Dans main.go, vous écrivez le code principal :

package main
import (
"fmt"
"myproject/utils" // Import d’un package local
)
func main() {
message := utils.GetGreeting("Go")
fmt.Println(message)
}

Et dans utils/helper.go, vous placez une fonction utilitaire :

package utils
func GetGreeting(name string) string {
return "Bonjour, " + name + " !"
}

Avec cette structure, votre code est propre, modulaire et facile à maintenir.

Les types de données

Go est un langage de programmation qui repose sur un système de typage statique. Cela signifie que chaque variable doit avoir un type défini lors de sa déclaration, et une fois que le type est attribué, il ne peut pas être modifié.

Ce principe assure une conformité stricte lors de l’exécution, réduisant ainsi les erreurs potentielles liées à l’utilisation incorrecte des variables. En conséquence, les développeurs peuvent écrire du code plus sécurisé et fiable, tout en bénéficiant d’optimisations de performance offertes par cette vérification anticipée des types.

Les types simples

Tout commence avec les types simples, la base de tout programme. Ces types permettent de manipuler des nombres, du texte ou des booléens. Mais Go, fidèle à sa philosophie, ne laisse rien au hasard.

Les nombres entiers

Go propose différentes tailles pour les entiers afin de répondre à des besoins spécifiques :

  • int : La taille dépend de votre architecture (32 ou 64 bits).
  • int8, int16, int32, int64 : Des tailles fixes.

Exemple :

var age int = 30
year := 2024 // Déclaration courte

Ce code illustre comment déclarer et attribuer des valeurs à des variables de type int en Go. On utilise ici deux méthodes :

  • la déclaration explicite avec le mot-clé ‘var’ où le type est spécifié
  • et la déclaration courte avec ’:=’ qui infère le type de la valeur assignée.

Les nombres à virgule flottante

Idéal pour les calculs nécessitant des décimales. Go propose deux tailles :

  • float32
  • float64 (ce dernier étant plus précis).

Exemple :

var temperature float64 = 37.5
pi := 3.14159

Les booléens

Les booléens sont simples et directs : true ou false. Ils sont souvent utilisés dans les conditions.

Exemple :

var isRunning bool = true
completed := false

Les chaînes de caractères (string)

Les chaînes de caractères sont des types de données très utiles. Elles sont utilisées pour représenter du texte, des noms de fichiers, des adresses, des adresses IP, etc.

Exemple :

var name string = "Alice"
greeting := "Hello, Go!"

Les types composites

Pour gérer des collections ou modéliser des entités complexes, Go propose des types composites, chacun conçu pour un usage spécifique.

Les tableaux (array)

Taille fixe, parfait pour des données dont la taille est connue à l’avance.

Exemple :

var numbers [5]int = [5]int{1, 2, 3, 4, 5}

Les slices

Une version plus flexible des tableaux, capable de croître ou rétrécir dynamiquement. C’est l’un des types les plus utilisés en Go.

Exemple :

numbers := []int{1, 2, 3, 4}
numbers = append(numbers, 5) // Ajoute un élément

Les maps

Go offre une structure clé-valeur appelée map, idéale pour organiser des données par association.

Exemple :

capitals := map[string]string{
"France": "Paris",
"Italie": "Rome",
}
capitals["Allemagne"] = "Berlin"

Les structures (struct)

Permettent de regrouper plusieurs types dans une entité personnalisée, idéale pour modéliser des objets réels.

Exemple :

type Person struct {
Name string
Age int
}
person := Person{Name: "Alice", Age: 30}

Conversions et compatibilités entre types

Go impose une conversion explicite entre les types, garantissant ainsi un contrôle strict sur les transformations de données. Cette approche réduit les erreurs potentielles en assurant que chaque conversion est intentionnelle et vérifiée par le programmeur.

Conversion d’un entier en nombre flottant

Pour passer d’un type entier (int) à un type flottant (float64), vous devez explicitement convertir le type :

var x int = 42
var y float64 = float64(x)

Autre exemple :

var x int = 123
var s string = fmt.Sprintf("%d", x)

Ces conversions évitent les erreurs subtiles et rendent le comportement du code plus prévisible.

Les opérateurs en Go

Les opérateurs en Go sont conçus pour être simples et intuitifs. Leur utilisation directe et claire s’inscrit dans l’esprit du langage, qui privilégie la lisibilité et la robustesse. Que ce soit pour des calculs simples, des comparaisons ou des manipulations avancées, ils couvrent une large gamme de besoins tout en restant faciles à comprendre et à maîtriser.

Les opérateurs arithmétiques

Ces opérateurs permettent d’effectuer des calculs mathématiques de base.

OpérateurDescriptionExemple
+Additionx + y
-Soustractionx - y
*Multiplicationx * y
/Divisionx / y
%Modulo (reste de division)x % y

Exemple :

a := 10
b := 3
fmt.Println("Addition :", a+b) // 13
fmt.Println("Division :", a/b) // 3 (division entière)
fmt.Println("Modulo :", a%b) // 1

👉 Attention : Les opérateurs comme / fonctionnent en division entière si les variables sont des entiers (int). Pour une division décimale, utilisez des types float64.

Les opérateurs relationnels

Les opérateurs relationnels permettent de comparer deux valeurs. Ils retournent toujours un résultat de type bool (true ou false).

OpérateurDescriptionExemple
==Égal àx == y
!=Différent dex != y
<Inférieur àx < y
<=Inférieur ou égal àx <= y
>Supérieur àx > y
>=Supérieur ou égal àx >= y

Exemple :

x := 5
y := 10
fmt.Println("x == y :", x == y) // false
fmt.Println("x < y :", x < y) // true

Les opérateurs logiques

Les opérateurs logiques sont utilisés pour combiner ou inverser des expressions conditionnelles.

OpérateurDescriptionExemple
&&ET logiquex > 0 && y > 0
||OU logiquex > 0 || y > 0
!NON logique (inversion)!true

Exemple :

a := 5
b := 10
fmt.Println("a > 0 && b > 0 :", a > 0 && b > 0) // true
fmt.Println("a < 0 || b > 0 :", a < 0 || b > 0) // true
fmt.Println("!(a > b) :", !(a > b)) // true

Les opérateurs d’affectation

Les opérateurs d’affectation servent à attribuer ou modifier la valeur d’une variable.

OpérateurDescriptionExemple
=Affectationx = y
+=Ajout et affectationx += y
-=Soustraction et affectationx -= y
*=Multiplication et affectationx *= y
/=Division et affectationx /= y
%=Modulo et affectationx %= y

Exemple :

x := 10
x += 5 // x = x + 5
fmt.Println(x) // 15
x *= 2 // x = x * 2
fmt.Println(x) // 30

Les opérateurs sur les bits

Les opérateurs bit-à-bit permettent de manipuler directement les bits des nombres. Ces opérateurs sont souvent utilisés dans des cas spécifiques, comme le traitement des données binaires.

OpérateurDescriptionExemple
&ET bit-à-bitx & y
|OU bit-à-bitx | y
^OU exclusif (XOR)x ^ y
&^AND NOT (effacement de bits)x &^ y
<<Décalage à gauchex << 1
>>Décalage à droitex >> 1

Exemple :

a := 6 // 110 en binaire
b := 3 // 011 en binaire
fmt.Println("a & b :", a & b) // 2 (010 en binaire)
fmt.Println("a | b :", a | b) // 7 (111 en binaire)
fmt.Println("a ^ b :", a ^ b) // 5 (101 en binaire)

Exercice pratique : Calcul simple avec des opérateurs

Écrivons un petit programme qui utilise plusieurs opérateurs pour effectuer des calculs simples basés sur des entrées utilisateur.

package main
import (
"fmt"
)
func main() {
var a, b int
fmt.Print("Entrez le premier nombre : ")
fmt.Scanln(&a)
fmt.Print("Entrez le deuxième nombre : ")
fmt.Scanln(&b)
fmt.Println("Addition :", a+b)
fmt.Println("Soustraction :", a-b)
fmt.Println("Multiplication :", a*b)
if b != 0 {
fmt.Println("Division :", a/b)
} else {
fmt.Println("Division par zéro impossible")
}
fmt.Println("Modulo :", a%b)
}

Les structures de contrôle en Go

Les structures de contrôle en Go permettent de gérer le flux d’exécution de votre programme en fonction de conditions ou d’itérations. Simples mais puissantes, elles s’intègrent parfaitement dans la philosophie minimaliste et efficace du langage. Voici une introduction pratique pour comprendre et maîtriser ces structures essentielles.

Les conditions : if, else if, et else

Go utilise des conditions pour exécuter du code en fonction de critères. La syntaxe est similaire à celle d’autres langages, mais sans parenthèses autour de la condition (même si elles sont autorisées).

Exemple simple :

age := 18
if age >= 18 {
fmt.Println("Vous êtes majeur.")
} else {
fmt.Println("Vous êtes mineur.")
}

Avec plusieurs cas :

score := 85
if score >= 90 {
fmt.Println("Excellent")
} else if score >= 75 {
fmt.Println("Bien")
} else {
fmt.Println("À améliorer")
}

Les alternatives conditionnelles : switch

Le switch en Go est une alternative élégante aux chaînes de if-else complexe. Il est simple à utiliser et puissant grâce à des fonctionnalités avancées.

  • Exemple de base :

    day := "mardi"
    switch day {
    case "lundi":
    fmt.Println("Début de la semaine")
    case "mardi", "mercredi":
    fmt.Println("Milieu de semaine")
    case "jeudi", "vendredi":
    fmt.Println("Presque le week-end")
    default:
    fmt.Println("C'est le week-end !")
    }
  • Switch sans expression : Lorsque vous omettez l’expression du switch, chaque case agit comme une condition indépendante :

    num := 7
    switch {
    case num%2 == 0:
    fmt.Println("Nombre pair")
    case num%2 != 0:
    fmt.Println("Nombre impair")
    }

👉 Contrairement à d’autres langages, les blocs case n’ont pas besoin de break : l’exécution s’arrête automatiquement après chaque bloc.

Les boucles : for

Go simplifie la gestion des boucles avec une unique structure, la boucle for. Elle peut remplacer des constructions comme while ou do-while présentes dans d’autres langages.

  • Boucle classique :

    for i := 0; i < 5; i++ {
    fmt.Println("Itération :", i)
    }
  • Boucle while simulée : En Go, une boucle for sans initialisation ni incrémentation agit comme un while.

    i := 0
    for i < 5 {
    fmt.Println("i vaut :", i)
    i++
    }
  • Boucle infinie : Une boucle infinie est déclarée avec un for sans condition.

    for {
    fmt.Println("Boucle infinie")
    break // Nécessite une condition pour sortir
    }

Contrôler le flux dans les boucles : break, continue et goto

Go offre des mots-clés pour manipuler le comportement des boucles.

  • Sortir d’une boucle : break

    for i := 0; i < 10; i++ {
    if i == 5 {
    break
    }
    fmt.Println(i)
    }
  • Passer à l’itération suivante : continue

for i := 0; i < 10; i++ {
if i%2 == 0 {
continue
}
fmt.Println(i) // Affiche uniquement les nombres impairs
}
  • Sauter à un label : goto

    i := 0
    for {
    if i == 5 {
    goto End
    }
    i++
    }
    End:
    fmt.Println("Boucle terminée.")

goto est à utilisé dans les cas où il est impossible d’utiliser break ou continue.

Exercice

Voici la version en Go du jeu de devinette, adaptée pour respecter la logique de Go tout en reprenant l’exercice Python. Go est parfait pour ce type d’exercice grâce à sa simplicité et sa performance.

L’objectif de ce programme est de créer un jeu de devinette où l’utilisateur tente de trouver un nombre mystère choisi à l’avance par le programme. Le but est de maîtriser les bases de Go, comme les boucles, les conditions, et l’interaction utilisateur.

Ce que doit contenir le programme :

  1. Un nombre à deviner : Un nombre fixe (par exemple, 42) que l’utilisateur doit deviner.
  2. Des messages d’accueil : Des instructions pour expliquer à l’utilisateur comment jouer.
  3. Un compteur d’essais : Une variable qui compte les tentatives.
  4. Une boucle de jeu : Une boucle qui continue jusqu’à ce que le nombre mystère soit trouvé.
  5. Des comparaisons : Des indices (plus grand ou plus petit) pour guider l’utilisateur.
  6. Un message de victoire : Un message pour féliciter l’utilisateur avec le nombre d’essais utilisés.

Conclusion

Vous avez maintenant appris les bases de Go, et vous êtes prêt à développer vos premières applications avec Go. Dans les prochaines semaines, j’aborderai d’autres sujets comme :

  • Les fonctions
  • Les structures
  • Les interfaces
  • Les tests
  • Les goroutines
  • Les channels
  • Les packages
  • Les dépendances
  • Les dépôts

Plus d’infos

Livres