Les packages dans le langage de programmation Go

Ce chapitre vous explique les packages en GoLang. Ils permettent de déplacer des portions de votre code dans d’autres fichiers afin de mieux organiser et maintenir votre programme. Vous allez apprendre à créer et gérer des packages dans le langage de programmation Go.

Définition

Jusqu'ici nous n'avons écrit notre code que dans un seul fichier, pour l'instant c'était tolérable car la taille de note code était petite, mais plus votre code va grandir plus vous allez vite vous rendre compte qu'il est nécessaire de déplacer des portions de votre code dans d'autres fichiers afin de mieux organiser et maintenir votre programme, et c'est là qu'interviennent les packages !

Un package n'est rien d'autre qu'un répertoire contenant des fichiers de code go, qui peut être exécuté par d'autres fichiers go.

Comme nous en avons discuté au début de nos chapitres, il existe deux types de packages :

  • Package exécutable
  • Package utilitaire

Dans un package exécutable on retrouve le fameux package main qui permet d'informer votre compilateur Go que le paquet doit être compilé en tant que programme exécutable au lieu d'un package utilitaire.

Un package utilitaire n'est pas auto-exécutable, il améliore plutôt les fonctionnalités d'un package exécutable en lui fournissant des fonctionnalités.

Création de packages

Où créer mon package ?

Pour importer un paquet, il faut utiliser le mot-clé import suivi du nom du paquet.

Lorsque vous créez un paquet et que vous l'importez sur votre package principal, votre compilateur va d'abord chercher le répertoire du paquet dans le $GOROOT/src/ et si répertoire n'existe pas il va le cherchera dans le dossier $GOPATH/src/.

Information

$GOROOT et $GOPATH sont deux variables d'environnement créez lors de l'installation de GO.

Il est possible d'afficher toutes vos variables d'environnement Go comme suit :

go env
Résultat :
set GOCACHE=C:\Users\hatim\AppData\Local\go-build
...
set GOPATH=C:\Users\hatim\go
set GOROOT=C:\Go
...        

Je vais volontairement importer un package qui n'existe pas, pour vous prouver qu'il cherche bel et bien vos packages dans ces deux chemins :

package main
import (
    "aucunpackage"
    "fmt"
)

func main() {
    fmt.Println(aucunpackage.affiche())
}
Erreur :
cannot find package "aucunpackage" in any of:
C:\Go\src\aucunpackage (from $GOROOT)
C:\Users\hatim\go\src\aucunpackage (from $GOPATH)

Le compilateur nous avertis qu'il ne retrouve pas le package dans mon dossier $GOROOT et $GOPATH. Il est donc nécessaire de déposer vos packages dans un des deux chemins.

Arborescence

Dans cet nouvel exemple, nous allons créer un simple package qui nous permet d'afficher un nom et un sexe, mais avant de toucher à du code on va d'abord réfléchir à notre arborescence

Déjà premièrement on va déposer nos packages comme go nous le demande à savoir dans le dossier $GOPATH/src/, qui est l'équivalent sur mon ordinateur au chemin C:\Users\hatim\go\src\ (tapez la commande go env pour connaître le chemin de $GOPATH/src/).

Ensuite pour créer un package il faut créer un dossier avec le nom de notre package suivi d'un fichier (même nom que le package de préférence) ou on déposera le code Go de notre package.

Dans l'exemple qui suit notre package se nommera affichage et notre package exécutable se nommera main.go. Ce qui nous donnera l'arborescence suivante :

$GOPATH/src
├── affichage
| ├── affichage.go
main.go        

Création du package

Voici à quoi va ressembler notre fichier affichage.go

package affichage

var Nom string = "Hatim"
var sexe string = "masculin"

func AfficheSexe() string {
    return Nom + " est de sexe " + sexe
}

Attention

Go exporte une variable dans un autre package si et seulement si le nom de la variable commence par une majuscule. Toutes les autres variables ne commençant pas par une lettre majuscule sont privées du paquet.

La ligne de code package affichage indique à notre compilateur qu'il s'agit bien d'un package utilitaire nommé "affichage". Ensuite pour le reste du code je déclare deux variables et une fonction qui peuvent être réutilisées depuis le fichier main.go une fois qu'il aura importé le package.

Il ne reste plus maintenant qu'à importer le package affichage dans le fichier main.go et par la suite il sera possible depuis le fichier main.go d'utiliser les fonctions et les variables du package affichage.

Voici à quoi va ressembler main.go :

package main

import (
    "affichage"
    "fmt"
)

func main() {
    fmt.Println("Je m'appelle", affichage.Nom)
    fmt.Println(affichage.AfficheSexe())
}
Résultat :
Je m'appelle Hatim
Hatim est de sexe masculin.        

Imbrication de paquets

Nous pouvons imbriquer un paquet dans un paquet. Tout ce que nous avons à faire c'est de fournir le chemin relatif du paquet imbriqué.

Nous allons rajouter dans notre exemple précèdent un sous-package nommé passion avec une fonction qui retourne un string. Notre nouvelle arborescence ressemblera à ceci :

$GOPATH/src
├── affichage
| ├── affichage.go
| ├── passion
|   ├── passion.go
main.go        

Voici à quoi va ressembler notre fichier passion.go :

package passion

func AffichagePassion() string {
    return "j'aime programmé en Go !"
}

Et voici à quoi va ressembler notre fichier main.go :

package main

import (
    "affichage"
    "affichage/passion" // chemin relatif
    "fmt"
)

func main() {
    fmt.Println("Je m'appelle", affichage.Nom)
    fmt.Println(affichage.AfficheSexe())
    fmt.Println(passion.AffichagePassion())
}

ici on utilise le chemin relatif pour importer notre package passion imbriqué dans notre package affichage.

Résultat :
Je m'appelle Hatim
Hatim est de sexe masculin
j'aime programmé en Go !.        

Espace commentaire

Écrire un commentaire

Rejoignez la discussion

Vous devez être connecté pour poster un message.

28 commentaires

ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Si vous avez d'autres soucis sur le typage ou l'exportation, vérifiez bien vos majuscules avant de poster ici. C'est 90% des erreurs au début.

07/04/2019 à 14:56
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Oui, le but est de masquer les détails d'implémentation. Si tu veux y accéder, crée un getter avec une majuscule.

07/04/2019 à 10:06
imbert-julien
Membre Actif
Avatar de imbert-julien
imbert-julien
Membre Actif

Je n'arrive pas à accéder à ma variable privée depuis mon fichier main. C'est normal ?

07/04/2019 à 05:34
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Oui, utilise go env GOPATH ou go env GOROOT directement pour récupérer juste la valeur. C'est plus propre pour les scripts.

07/04/2019 à 00:24
sdumas
Membre Actif
Avatar de sdumas
sdumas
Membre Actif

Question sur go env, on peut filtrer le résultat ?

06/04/2019 à 18:15
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Oui, mais tu devras gérer les alias à l'import pour éviter les conflits de nommage :

import (
    alias1 "mon/dossier/un"
    alias2 "mon/dossier/deux"
)
06/04/2019 à 14:11
vlecoq
Membre Actif
Avatar de vlecoq
vlecoq
Membre Actif

Est-ce qu'on peut avoir deux packages avec le même nom dans des répertoires différents ?

06/04/2019 à 08:19
qblin
Membre Actif
Avatar de qblin
qblin
Membre Actif

Merci pour l'exemple sur l'imbrication, c'était le point le plus flou pour moi.

06/04/2019 à 01:39
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Si tu as un import circulaire, c'est que ton architecture est bancale. Tu dois extraire les éléments communs dans un troisième package tiers.

05/04/2019 à 20:23
cecile-dumont
Membre Actif
Avatar de cecile-dumont
cecile-dumont
Membre Actif

J'ai eu un souci de circular import. Comment on gère ça proprement ?

05/04/2019 à 15:03
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

La règle de la majuscule s'applique aussi aux constantes. Tu fais const MaConstante = 10 et c'est bon.

05/04/2019 à 08:24
lambert-lucie
Membre Actif
Avatar de lambert-lucie
lambert-lucie
Membre Actif

Si je veux partager une constante entre deux packages, je fais comment ?

05/04/2019 à 02:33
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

C'est l'ancienne méthode. Aujourd'hui on utilise les go.mod, mais comprendre la structure des packages manuels comme expliqué ici est indispensable pour debugger les vieux projets.

04/04/2019 à 19:07
patrick81
Membre Actif
Avatar de patrick81
patrick81
Membre Actif

C'est pas un peu archaïque de devoir tout mettre dans $GOPATH/src ?

04/04/2019 à 11:38
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Fais un go env et vérifie que ton dossier est bien à l'intérieur du chemin affiché. Si tu es en dehors, Go ignorera tout.

04/04/2019 à 04:02
stephane39
Membre Actif
Avatar de stephane39
stephane39
Membre Actif

J'ai essayé de structurer mon code comme ça :

$GOPATH/src
├── utils
| ├── helper.go

Mais main.go refuse d'importer utils.

03/04/2019 à 20:19
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

$GOROOT c'est pour l'installation de Go lui-même. $GOPATH c'est ton espace de travail. Ne touche jamais au $GOROOT, c'est la base.

03/04/2019 à 13:10
rousseau-michel
Membre Actif
Avatar de rousseau-michel
rousseau-michel
Membre Actif

C'est quoi la différence réelle entre $GOROOT et $GOPATH pour un débutant ?

03/04/2019 à 05:29
umichel
Membre Actif
Avatar de umichel
umichel
Membre Actif

C'est bon, j'avais oublié de mettre le dossier passion directement dans affichage. Ça compile.

02/04/2019 à 23:16
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Assure-toi que ton passion.go commence bien par package passion. Si t'as une erreur, poste ton arborescence exacte.

02/04/2019 à 15:26
huet-aurore
Membre Actif
Avatar de huet-aurore
huet-aurore
Membre Actif

J'ai une erreur sur import "affichage/passion". Il me dit que le module est introuvable.

02/04/2019 à 09:21
humbert-lucy
Membre Actif
Avatar de humbert-lucy
humbert-lucy
Membre Actif

Merci pour l'article. Par contre, l'imbrication de paquets avec le chemin relatif, c'est propre mais ça devient vite le bazar si on a 50 packages.

02/04/2019 à 01:58
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Exactement. En Go, la visibilité est liée à la casse. Majuscule = exporté, minuscule = privé. C'est la règle de base pour l'encapsulation.

01/04/2019 à 18:40
cmoreau
Membre Actif
Avatar de cmoreau
cmoreau
Membre Actif

Petite question bête : si je veux que sexe soit accessible depuis main.go, je suis obligé de mettre une majuscule ?

01/04/2019 à 13:45
ajdaini-hatim
Auteur Rédacteur Secouriste Actif
Avatar de ajdaini-hatim
ajdaini-hatim
Auteur Rédacteur Secouriste Actif

Tente un go install dans le répertoire de ton package avant de lancer ton main.go. C'est souvent là que ça coince.

01/04/2019 à 07:17

Rejoindre la communauté

Recevoir les derniers articles gratuitement en créant un compte !

S'inscrire