dependencies - dependency - ¿Algún buen consejo sobre cómo evitar el ciclo de importación en Go?
circular dependencies in projects graph projects in cycle are (3)
Dado que la relación de importación se vuelve cada vez más compleja a medida que crece el código, estoy ansioso por saber cómo evitar el ciclo de importación de manera más eficiente en Go.
Otra opción es visualizar las dependencias en su proyecto. Esto se puede hacer con la herramienta CLI godepgraph . Puedes instalarlo con:
go get -u github.com/kisielk/godepgraph
Y luego graphvis para encontrar ciclos de importación en su aplicación con la ayuda de otra herramienta CLI graphvis . Con estas herramientas, puede visualizar las dependencias del paquete:
godepgraph -s path/to/my/package | dot -Tpng -o godepgraph.png
open ./godepgraph.png
Estoy trabajando en un proyecto Go por un mes. Lo bueno es que Go es realmente muy eficiente. Pero después de un mes de desarrollo, ya tengo miles de líneas de código y muchos packages
. Para evitar el ciclo de importación es un problema importante para mí que cada vez que tengo un error en el ciclo de importación, no tengo idea de dónde puede estar el problema por primera vez.
El compilador de Go también solo tiene un aviso muy simple que siempre no es lo suficientemente bueno para localizar el problema rápidamente como: main.go:7:3: import cycle not allowed
. Solo lo ayudará a saber qué archivo puede causar el problema, pero nada más profundamente. Dado que la relación de import
vuelve cada vez más compleja a medida que crece el código, estoy ansioso por saber cómo evitar el ciclo de importación de manera más eficiente en Go. Cualquier ayuda es muy apreciada.
Para complementar la respuesta de jnml (que ayuda a "depurar" problemas de referencias circulares), puede usar la inversión de dependencia para romper esos ciclos, junto con la inyección de dependencia. Para una aplicación, siempre trato de seguir las pautas de la Arquitectura Limpia - mire here un ejemplo específico de Ir - y encuentro que la "implementación no declarativa" de Go de las interfaces (es decir, no tiene que decir explícitamente type MyStruct struct implements IfceSomething
) hace esto muy simple.
Entonces, si tiene paquetes A -> B -> C -> A
, crea InterfaceA
(un nombre relevante, obviamente, más relacionado con el comportamiento que el relacionado con el paquete :) en el paquete C y lo hace depender de esta interfaz en lugar de en paquete A, y se asegura de que el paquete A "implemente" esta interfaz.
Entonces solo tiene que proporcionar una implementación concreta de A a C en algún momento (hay muchas posibilidades aquí, generalmente hago este código de "pegamento" en el paquete principal que conoce todas las dependencias).
go list -f ''{{join .Deps "/n"}}'' <import-path>
Mostrará dependencias de importación para el paquete en <import-path>
- o en el directorio actual si <import-path>
se deja en blanco. Alternativamente
go list -f ''{{join .DepsErrors "/n"}}'' <import-path>
con suerte muestra información útil en su caso. Ver también el resultado de
go help list
para obtener información adicional sobre la herramienta ir lista.