4 façons d'importer un package dans Go

La partie déclarative de l'importation de packages dans Go est plutôt ennuyeuse et banale. Il vous suffit de spécifier la directive d' import et de répertorier les packages importés. Les IDE modernes font ce travail pour vous - ils remplacent eux-mêmes les packages dans cette section, ce qui est très pratique. En outre, ils réduisent ce bloc afin qu'il n'interfère pas avec la vue de code. Je vous conseille d'étendre ce bloc et de l'étudier attentivement - vous y trouverez peut-être quelque chose d'inhabituel:


  package main import ( "github.com/vigo5190/goimports-example/a" foo "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" _ "github.com/vigo5190/goimports-example/c" ) 

Si l'importation standard, importez avec un synonyme et _ J'ai rencontré, puis importez de . Je n'en ai jamais vu auparavant.


Pour commencer, il convient de se rappeler comment les programmes on Go sont lancés.
La première chose et la plus importante - à la racine du projet (pour les bibliothèques et les packages autrement) se trouve le fichier main.go , qui, une fois développé, est géré par


 go run main.go 

Une particularité de ce fichier est que le package qui y est déclaré doit être main .


 package main import ( "fmt" ) func main() { fmt.Println("Hello habr.com!") } 

Essentiellement, le point d'entrée du programme est func main() dans le package main . Mais ce comportement peut être un peu piraté . La func init() été inventée pour cela. Cette fonction s'exécutera avant d'exécuter func main() . Cette fonction peut également être écrite dans vos packages. Il sera toujours exécuté lors de l'importation d'un package (pour être précis, il sera exécuté une fois que le package sera importé pour la première fois dans votre programme). Il est également intéressant de comprendre que init() sera exécuté lorsque les tests de ce package seront exécutés.


Exemples de packages


Le package a exporte uniquement la variable, mais ne l'initialise pas.


github.com/vigo5190/goimports-example/a
 package a var Foo string 

Le package b exporte la variable et l'initialise dans init() .


github.com/vigo5190/goimports-example/b
 package b var Foo string func init() { Foo = "bar" } 

Le package c exporte la variable, l'initialise dans init() et affiche la valeur dans stdout.


github.com/vigo5190/goimports-example/c
 package c import "fmt" var Foo string func init() { Foo = "bar" fmt.Printf("%#v\n", Foo) } 

Importer "simple"


Dans cet exemple, nous importons 2 packages et exportons les valeurs des variables exportées vers stdout.


 package main import ( "fmt" "github.com/vigo5190/goimports-example/a" "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", b.Foo) } 

Nous obtenons


 go run main.go "" "bar" 

Que se passe-t-il réellement dans ce code. Dans la section d' import , 2 packages a et b importés. Dans le package a variable avec une valeur par défaut est déclarée (pour les chaînes - une chaîne vide). Dans le package b , la valeur de la variable a été initialisée dans init() valeur "bar" . Pour accéder aux variables de chaque package, utilisez une entrée de la forme <_>.<_> .


Importer un synonyme


 package main import ( "fmt" "github.com/vigo5190/goimports-example/a" foo "github.com/vigo5190/goimports-example/b" bar "github.com/vigo5190/goimports-example/a" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", foo.Foo) fmt.Printf("%#v\n", bar.Foo) } 

Nous obtenons


 go run main.go "" "bar" "" 

Comme vous pouvez le voir dans l'exemple, le package b attribuer le synonyme foo . Dans ce cas, le package a a importé plusieurs fois - la deuxième fois sous la bar alias.


Les packages sont importés en définissant des synonymes dans plusieurs cas:


  • Le nom du paquet importé n'est pas pratique / moche / ... et je veux en utiliser un autre;
  • Le nom de celui importé croise le nom d'un autre paquet;
  • Je veux remplacer le package de manière transparente - les interfaces du package doivent correspondre.

Exemple d'utilisation justifiable d'un synonyme

Par exemple, lors de l'importation de github.com/sirupsen/logrus :


 package db import( log "github.com/sirupsen/logrus" ) 

Souligner l'importation


 package main import ( "fmt" "github.com/vigo5190/goimports-example/a" _ "github.com/vigo5190/goimports-example/c" ) func main() { fmt.Printf("%#v\n", a.Foo) } 

Nous obtenons


 go run main.go "bar" "" 

Comme le montre le code, nous importons deux packages: a et c . Dans ce cas, le package c précédé de _ et le package lui-même n'est utilisé en aucune façon. Cette technique est utilisée pour exécuter init() partir d'un package.


Dans notre exemple, "bar" est apparu dans la sortie sur la première ligne, car cette sortie est dans la fonction d'initialisation du package c .


Exemple d'utilisation justifiée _

Par exemple, lors de l'importation de github.com/lib/pq :


 package db import( _ "github.com/lib/pq" ) 

dans init() lib/pq le code est:


 func init() { sql.Register("postgres", &Driver{}) } 

qui enregistrera le pilote.


Importer un point c


 package main import ( "fmt" "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", a.Foo) fmt.Printf("%#v\n", Foo) } 

Nous obtenons


 go run main.go "" "bar" 

L'importation avec un point ajoute tous les champs exportés du package à la portée actuelle (plus précisément, la portée du fichier). Et maintenant, vous pouvez travailler avec les champs du package importé comme s'ils se trouvaient dans votre package.


Cette option doit être utilisée très soigneusement - un exemple ci-dessous.


Exemple 1
 package main import ( . "fmt" ) func main() { Println("Hello, habr.com!") } 

Nous obtenons:


 Hello, habr.com! 

Exemple 2
 package main import ( . "fmt" . "math" ) func main() { Printf("%v\n", Sqrt(9)) } 

Nous obtenons:


 3 

Importer avec point (et erreur)


 package main import ( "fmt" . "github.com/vigo5190/goimports-example/a" . "github.com/vigo5190/goimports-example/b" ) func main() { fmt.Printf("%#v\n", Foo) } 

Nous obtenons


 go run main.go # command-line-arguments ./main.go:7:2: Foo redeclared during import "github.com/vigo5190/goimports-example/b" previous declaration during import "github.com/vigo5190/goimports-example/a" ./main.go:7:2: imported and not used: "github.com/vigo5190/goimports-example/b" 

Comme vous pouvez le voir dans la sortie, lors de l'importation de packages avec des champs qui se croisent dans la portée actuelle, nous obtenons une erreur de compilation.


Par conséquent, détrompez-vous avant d'utiliser une telle importation - vous pouvez obtenir une erreur de manière complètement inattendue.


Total


Malgré les limitations de syntaxe strictes, vous pouvez faire beaucoup de choses non standard dans Go. Les fonctions d'importation discutées ci-dessus démontrent qu'avec seulement quelques opérateurs, vous pouvez modifier considérablement le comportement d'un programme. L'essentiel, quand on utilise toutes ces opportunités, n'est pas de se tirer une balle dans le pied . Et n'oubliez pas qu'il vaut mieux écrire du code simple et compréhensible que du code complexe et «cool».


PS


Des exemples de code avec lesquels jouer sont sur le github .

Source: https://habr.com/ru/post/fr413563/


All Articles