Utiliser les imports de package go

Dans cet article nous examinerons plusieurs variantes du mot-clé import. Une déclaration d'import signale au compilateur qu'un fichier source contenant l'import d'un paquet go dépend de ce paquet. Ce qui permet à ce fichier source d'utiliser des identificateurs (variables, fonctions) contenus dans ce paquet.
Bien entendu, un paquet ne peut pas s'inclure lui-même.
Importer un paquet sans utiliser les fonctionnalités qu'il contient provoque une erreur de compilation. C'est un peu pénible, mais cela permet de garder un code propre et concis ne contenant que ce qui est nécessaire à l'exécution du code. L'effet bénéfique de cette règle stricte est de limiter la taille du binaire issue de la compilation au strict nécessaire.

Comment importer et utiliser différents paquets go ayant le même nom ?

Si on essaye d'utiliser deux packages go ayant le même nom, comme math/rand et crypto/rand ou text/template et html/template, on obtient l'erreur suivante : rand redeclared as imported package name ainsi que des erreurs undefined:.
Pour inclure deux packages ayant le même nom, il faut renommer l'un d'entre eux au moment de l'import. Comme dans cet exemple de code où le package crypto/rand a été renommé en randcrypt de manière à ne pas être considéré comme déjà utilisé au moment de la compilation.
package main

import (
	"fmt"
	"math/rand"
	randcrypt "crypto/rand"
)

	func main() {
	fmt.Println("Au hasard : ", rand.Intn(100))
	b := make([]byte, 10)
	randcrypt.Read(b)
	fmt.Printf("Au hasard : %v\n", string(b))	
}

Fusionner un paquet dans le package qui l'importe

Lorsque, par exemple, on utilise la fonction Println du paquet fmt, il faut utiliser le nom du paquet fmt en tant que préfixe (on parle aussi d'identificateur qualifié ou qualified identifier). Ainsi, comme dans l'exemple de code précédent, on écrira fmt.Println("Au hasard : ", rand.Intn(100)) pour afficher à l'écran un nombre choisit au hasard entre 0 et 100.
golang permet, au moment de l'import, de préciser que l'on souhaite se passer des préfixes lors que l'on appelle une fonction d'un paquet. Un peu comme si le code du package étant fusionné dans le paquet où il est importé. Dans l'exemple ci-dessous, le paquet fmt est comme fusionné avec le paquet main:
package main

import (
	. "fmt"
)

func main() {
	Println("Appel de la fonction Println sans utliser le prefixe fmt")

}

Jouer sur les effets de bord

Décrire l'effet de bord est l'occasion de parler du mystérieux paquet expvar. Comme nous l'avons vu précédemment, le fait ne pas faire appel à des identificateurs contenus dans un paquet importé provoque une erreur de compilation. Ce qui est embêtant, car certains packages contiennent du code utilitaire apportant des fonctionnalités supplémentaires à un programme golang sans qu'il soit nécessaire de faire appel à ce code. Un peu à la manière d'un plug-in.
C'est le cas du package expvar qui contient un handler HTTP donnant des informations sur l'état d'une application web écrite en go. Voici un exemple d'utilisation :
package main

import (
	"net/http"
	_ "expvar"
)

func main() {
	http.ListenAndServe(":9999", nil)
}
Si on écrivait la ligne import "expvar", on obtiendrait une erreur de type imported and not used: "expvar". Mais l'indentificateur blanc (blank identifier) permet d'importer un paquet seulement pour ses effets de bord et pas forcément pour utiliser une de ses fonctions.
Vous pouvez exécuter le code ci-dessus, puis accéder à l'URL http://localhost:9999/debug/vars qui donne des informations sur les variables publiques de votre webapp. Lorsque la documentation parle de variable publique, il s'agit d'indicateurs sur le programme (comme les indicateurs sur la consommation mémoire, la pile ou le tas), mais pas sur les variables déclarées en dehors des fonctions.

Récapitulatif

Si vous avez bien suivi mon article jusqu'à maintenant, vous comprendrez que l'on peut donc écrire le code suivant sans erreur :
package main

import (
	. "fmt"
	"math/rand"
	"net/http"
	randcrypt "crypto/rand"
	_ "expvar"
)

func main() {
	Println("Au hasard : ", rand.Intn(100))
	b := make([]byte, 10)
	randcrypt.Read(b)
	Println("Au hasard : %v", string(b))
	http.ListenAndServe(":9999", nil)
}
Si on examine le code de la fonction principale :
  1. Println au lieu de fmt.Println ne pose pas de problème grâce à l'import-fusion . "fmt"
  2. On peut faire appel à deux paquets portant le même nom rand parce que l'un d'entre eux est renommé en randcrypt
  3. Nous bénéficions des handlers HTTP du paquet expvar grâce à l'effet de bord de l'import _ "expvar"

Étiquettes :   debuter 
Portrait de Benjamin BALET
Benjamin BALET
Consultant APM

Retrouvez mes cooordonées

Benjamin BALET sur viadeo






Vous aimerez aussi

Les lois de la réflexion

Une traduction du blog officiel de golang expliquant le mécanisme de la réflexion en Go.   Lire »

Comment écrire du code Go ?

Traduction d'une partie des spécifications officielles du langage Go, cet article explique comment développer en Go.   Lire »

Gobs le format natif d'échange de données en Go

Traduction d'un article du blog officiel expliquant comment échanger des données entre deux programmes golang grâce à un format natif   Lire »

Comment gérer efficacement les erreurs en golang ?

Préconisations officielles pour la gestion des erreurs dans un programme golang. Cet article complète les explications sur panic, defer et recover   Lire »

Les erreurs les plus courantes en golang

Quelques erreurs commises par les débutants en go et comment les éviter afin d'accélérer la compilation   Lire »

Commentaires

Soyez le premier à commenter cet article

Publier un commentaires

Tous les commentaires sont soumis à modération. Les balises HTML sont pour la plupart autorisées. Les liens contextuels et intéressants sont en follow.

(requis)
(requis)
(requis, mais non publié)
(recommandé si vous souhaitez être publié)