Découvrir les packages

Effectué

En Go, les packages s’apparentent aux bibliothèques ou aux modules dans d’autres langages de programmation. Vous pouvez empaqueter votre code et le réutiliser ailleurs. Le code source d’un package peut être distribué dans plusieurs fichiers .go. Jusqu’à présent, nous avons écrit le package main et avons fait quelques références à d’autres packages natifs.

Dans cette section, vous allez découvrir ce qu’est un package. Vous allez également apprendre à en créer un et à consommer des packages externes.

Package main

Comme vous l’avez peut-être remarqué, même le programme le plus simple en Go doit faire partie d’un package. En règle générale, le package par défaut est le package main, celui que nous avons utilisé jusqu’à présent. Si un programme fait partie du package main, Go génère un fichier binaire. Quand ce fichier est exécuté, il appelle la fonction main().

En d’autres termes, quand vous utilisez le package main, votre programme crée un exécutable autonome. Mais quand un programme fait partie d’un package autre que main, Go ne génère pas de fichier binaire. Il génère un fichier d’archive de package (fichier portant l’extension .a).

En Go, les noms de package suivent une convention. Un package utilise la dernière partie de son chemin d’importation comme nom. Par exemple, la bibliothèque Go standard contient un package appelé math/cmplx, qui fournit du code utile pour travailler avec des nombres complexes. Le chemin d’importation de ce package est math/cmplx, et vous l’importez comme ceci :

import "math/cmplx"

Pour faire référence à des objets du package, vous utilisez le nom du package, cmplx, comme ceci :

cmplx.Inf()

Créons un package.

Créer un package

Dans le répertoire $GOPATH/src, créez un répertoire nommé calculator. Création d’un fichier appelé sum.go. Le répertoire arborescent doit ressembler à ce répertoire :

src/
  calculator/
    sum.go

Initialisez le fichier sum.go avec le nom du package :

package calculator

Vous pouvez maintenant commencer à écrire les fonctions et les variables du package. Contrairement à d’autres langages de programmation, Go ne fournit pas les mots clés public ou private pour indiquer si une variable ou une fonction peut être appelée à partir de l’extérieur ou à l’intérieur du package. Mais Go suit deux règles simples :

  • Si vous souhaitez qu’un élément soit privé, commencez son nom par une lettre minuscule.
  • Si vous souhaitez qu’un élément soit public, commencez son nom par une lettre majuscule.

Nous allons donc ajouter le code suivant au package de calculatrice que nous créons :

package calculator

var logMessage = "[LOG]"

// Version of the calculator
var Version = "1.0"

func internalSum(number int) int {
    return number - 1
}

// Sum two integer numbers
func Sum(number1, number2 int) int {
    return number1 + number2
}

Examinons quelques éléments dans ce code :

  • La variable logMessage peut être appelée uniquement à partir du package.
  • Vous pouvez accéder à la variable Version depuis n’importe quel endroit. Nous vous recommandons d’inclure un commentaire pour décrire l’objectif de cette variable. (Cette description est utile pour toute personne qui utilise le package.)
  • La fonction internalSum peut être appelée uniquement à partir du package.
  • Vous pouvez accéder à la fonction Sum depuis n’importe quel endroit. Nous vous recommandons d’inclure un commentaire pour décrire l’objectif de cette fonction.

Pour vérifier que tout fonctionne, vous pouvez exécuter la commande go build dans le répertoire calculator. Si vous le faites, vous remarquerez qu’aucun binaire exécutable n’est généré.

Création d’un module

Vous avez placé les fonctionnalités de calculatrice dans un package. Maintenant, il est temps de mettre ce package dans un module. Les modules Go contiennent généralement des packages qui offrent des fonctionnalités connexes. Le module d’un package spécifie aussi le contexte dont Go a besoin pour exécuter le code que vous avez regroupé. Ces informations contextuelles incluent la version de Go pour laquelle votre code est écrit.

En outre, les modules aident les autres développeurs à référencer des versions spécifiques de votre code et à faciliter l’utilisation des dépendances. Un autre avantage est que le code source de notre programme n’a pas strictement besoin d’exister dans le répertoire $GOPATH/src. L’affranchissement de cette restriction simplifie l’utilisation de différentes versions de package dans d’autres projets en même temps.

Ainsi, afin de créer un module pour le package calculator, exécutez cette commande dans le répertoire racine ($GOPATH/src/calculator) :

go mod init github.com/myuser/calculator

Une fois cette commande exécutée, github.com/myuser/calculator devient le nom du module. Vous utiliserez ce nom pour le référencer dans d’autres programmes. La commande crée également un fichier appelé go.mod. Enfin, le répertoire arborescent ressemble maintenant à ce répertoire :

src/
  calculator/
    go.mod
    sum.go

Le contenu du fichier go.mod doit ressembler au code suivant. (La version de Go peut être différente.)

module github.com/myuser/calculator

go 1.14

Pour référencer votre package calculator dans d’autres programmes, vous devez l’importer en utilisant le nom du module. En l’occurrence, le nom est github.com/myuser/calculator. Examinons maintenant un exemple d’utilisation de ce package.

Notes

Historiquement, la gestion des dépendances en Go n’a pas été simple. Le système de gestion des dépendances est toujours un travail en cours. Si vous souhaitez en découvrir plus sur les modules, consultez cette série de billets publiés sur le blog Go.

Référencer un package local (un module)

Nous allons maintenant utiliser le package. Nous allons continuer avec l’exemple d’application que nous avons utilisé. Cette fois, au lieu d’avoir la fonction sum dans le package main, nous allons utiliser celle que nous avons créée dans le package calculator.

La structure arborescente des fichiers doit maintenant ressembler à ceci :

src/
  calculator/
    go.mod
    sum.go
  helloworld/
    main.go

Nous allons utiliser ce code pour le fichier $GOPATH/src/helloworld/main.go :

package main

import (
  "fmt"
  "github.com/myuser/calculator"
)

func main() {
    total := calculator.Sum(3, 5)
    fmt.Println(total)
    fmt.Println("Version: ", calculator.Version)
}

Notez que l’instruction import utilise le nom du package que vous avez créé : calculator. Pour appeler la fonction Sum à partir de ce package, vous devez inclure le nom du package sous la forme calculator.Sum. Enfin, vous avez également maintenant accès à la variable Version. Vous l’appelez comme suit : calculator.Version.

Le programme n’est toujours pas prêt à être exécuté. Vous devez indiquer à Go que vous utilisez des modules pour référencer d’autres packages. Pour ce faire, exécutez la commande suivante dans le répertoire $GOPATH/src/helloworld :

go mod init helloworld

Dans la commande précédente, helloworld est le nom du projet. Cette commande crée un fichier go.mod ; le répertoire arborescent ressemble maintenant à ceci :

src/
  calculator/
    go.mod
    sum.go
  helloworld/
    go.mod
    main.go

Quand vous ouvrez le fichier go.mod, vous devez voir un code semblable au suivant. (La version de Go peut être différente.)

module helloworld

go 1.14

Étant donné que vous référencez une copie locale du module, vous devez informer Go que vous ne souhaitez pas utiliser un emplacement distant. Vous devez donc modifier manuellement le fichier go.mod pour inclure la référence, comme suit :

module helloworld

go 1.14

require github.com/myuser/calculator v0.0.0

replace github.com/myuser/calculator => ../calculator

Le mot clé replace spécifie d’utiliser un répertoire local au lieu d’un emplacement distant pour le module. En l’occurrence, étant donné que les programmes helloworld et calculator se trouvent dans $GOPATH/src, l’emplacement est simplement ../calculator. Si la source du module se trouve dans un emplacement différent, vous définissez le chemin local ici.

Exécutez le programme à l’aide de la commande suivante :

go run main.go

La sortie doit se présenter comme suit :

8
Version:  1.0

Défi 1

Que se passe-t-il si vous essayez d’appeler la variable logMessage ou la fonction internalSum à partir du package calculator dans l’application principale ? S’exécute-t-elle ? Essai

Solution au défi :

package main

import (
 "fmt"
 "github.com/myuser/calculator"
)

func main() {
    total := calculator.internalSum(5)
    fmt.Println(total)
    fmt.Println("Version: ", calculator.logMessage)
}

Publier un package

La publication d’un package Go est relativement simple. Vous devez simplement rendre le code source du package disponible publiquement. La plupart des développeurs utilisent GitHub pour mettre des packages à la disposition du public. C’est pourquoi vous trouverez parfois des références à github.com dans les instructions d’importation.

Par exemple, si vous souhaitez publier votre package calculator sur votre compte GitHub, vous devez créer un dépôt nommé calculator. L’URL doit ressembler à celle-ci :

https://github.com/myuser/calculator

Vous allez définir la version de vos packages en étiquetant votre dépôt, comme suit :

git tag v0.1.0
git push origin v0.1.0

Les développeurs qui souhaitent utiliser votre package (y compris vous-même) y font référence comme suit :

import "github.com/myuser/calculator"

Parlons plus en détail de la façon de référencer des packages tiers.

Référencer des packages externes (tiers)

Parfois, vos programmes doivent référencer des packages écrits par d’autres développeurs. En règle générale, ces packages sont disponibles sur GitHub. Les instructions suivantes pour référencer des packages tiers fonctionnent, que vous développiez un package (un package autre que main) ou un programme autonome (le package main).

Nous allons ajouter une référence au package rsc.io/quote :

package main

import (
    "fmt"
    "github.com/myuser/calculator"
    "rsc.io/quote"
)

func main() {
    total := calculator.Sum(3, 5)
    fmt.Println(total)
    fmt.Println("Version: ", calculator.Version)
    fmt.Println(quote.Hello())
}

Si vous utilisez Visual Studio Code, le fichier go.mod est mis à jour quand vous l’enregistrez. Elle se présente maintenant comme suit :

module helloworld

go 1.14

require (
    github.com/myuser/calculator v0.0.0
    rsc.io/quote v1.5.2
)

replace github.com/myuser/calculator => ../calculator

Comme vous pouvez le constater, rsc.io/quote référence une version spécifique du package. Quand vous avez besoin de mettre à niveau les dépendances de votre programme, vous devez changer la version ici.

Réexécutez le programme à l’aide de la commande suivante :

go run main.go

La sortie doit ressembler à ceci :

8
Version:  1.0
Hello, world.

Toutes les références futures aux packages tiers devront se trouver dans le fichier go.mod. Quand vous exécutez ou compilez l’application, Go télécharge toutes ses dépendances.