web-dev-qa-db-fra.com

Un bon conseil sur la façon d'éviter le cycle d'importation dans Go?

Je travaille sur un projet Go depuis un mois. La bonne chose est que Go est vraiment très efficace. Mais après un mois de développement, j'ai déjà des milliers de lignes de code et plusieurs packages. Pour éviter le cycle d'importation est un problème majeur pour moi que chaque fois que j'ai une erreur de cycle d'importation, je ne sais pas où le problème peut être la première fois.

Le compilateur Go n'a également qu'un avis très simple qui n'est pas toujours assez bon pour localiser rapidement le problème comme: main.go:7:3: import cycle not allowed. Cela ne vous aidera qu'à savoir quel fichier peut causer le problème, mais rien de plus profond. Étant donné que la relation import devient de plus en plus complexe au fur et à mesure que le code se développe, je suis impatient de savoir comment éviter plus efficacement le cycle d'importation dans Go. Toute aide est très appréciée.

40
Reck Hou
go list -f '{{join .Deps "\n"}}' <import-path>

Affiche les dépendances d'importation pour le package à <import-path> - ou dans le répertoire courant si <import-path> est laissé vide. Alternativement

go list -f '{{join .DepsErrors "\n"}}' <import-path>

nous espérons que vous trouverez des informations utiles dans votre cas. Voir aussi la sortie de

go help list

pour plus d'informations sur l'outil go list.

57
zzzz

Pour compléter la réponse de jnml (ce qui aide à "déboguer" les problèmes de références circulaires), vous pouvez utiliser inversion de dépendance pour briser ces cycles, couplé à l'injection de dépendance. Pour une application, j'essaie toujours de suivre les directives de Clean Architecture - voir ici pour un exemple spécifique à Go - et je trouve que "l'implémentation non déclarative" de Go d'interfaces (autrement dit, vous n'avez pas à dire explicitement type MyStruct struct implements IfceSomething) rend cela très simple.

Donc, si vous avez des packages A -> B -> C -> A, vous créez InterfaceA (un nom pertinent, évidemment, plus lié au comportement qu'au package :) dans le package C et le faites dépendre de cette interface au lieu du package A, et vous vous assurez que le package A "implémente" cette interface.

Ensuite, il vous suffit de fournir une implémentation concrète de A à C à un moment donné (de nombreuses possibilités ici, je fais généralement ce code "glue" dans le package principal qui connaît toutes les dépendances).

41
mna

Étant donné que la relation d'importation devient de plus en plus complexe au fur et à mesure que le code se développe, j'ai hâte de savoir comment éviter plus efficacement le cycle d'importation dans Go.

Une autre option consiste à visualiser les dépendances dans votre projet. Cela peut être fait avec l'outil CLI godepgraph . Vous pouvez l'installer avec:

go get -u github.com/kisielk/godepgraph

Et puis utilisez-le pour trouver des cycles d'importation dans votre application à l'aide d'un autre outil CLI graphvis . Ayant ces outils, vous pouvez visualiser les dépendances des packages:

godepgraph -s path/to/my/package | dot -Tpng -o godepgraph.png
open ./godepgraph.png

pour trouver des cycles dans mon code: enter image description here

7
skovtunenko