This article also publishes a personal CSDN blog: https://blog.csdn.net/ggq89/article/details/81148558
Believe that Gopher
a lot of writing Golang
procedures have encountered import cycle not allowed
problems, I recently studied go-ethereum source code, found that the definition interface
can also solve the problem, but also to solve the situation can not be solved even sub-package, and the score package is more simple and fast. The following are explained individually and in both 分包
定义接口
ways.
1. Application Scenarios
Suppose you have the following usage scenarios:
A
Is the framework-level structure of the application, which A
contains the sub-modules B
and C
pointers;
B
In order to facilitate the use of other sub-modules (such as) the application of the C
function, so in its structure contains A
the pointer;
C
To invoke A
a method in the package;
2. Code implementation
The procedure is broadly as follows:
package a
The code is as follows:
package aimport ( "fmt" "github.com/ggq89/mutualdep/b" "github.com/ggq89/mutualdep/c")type A struct { Pb *b.B Pc *c.C}func New(ic int) *A { a := &A{ Pc: c.New(ic), } a.Pb = b.New(a) return a}func Printf(v int) { fmt.Printf("%v", v)}
package b
The code is as follows:
package bimport ( "github.com/ggq89/mutualdep/a")type B struct { Pa *a.A}func New(a *a.A) *B { return &B{ Pa: a, }}func (b *B) DisplayC() { b.Pa.Pc.Show()}
package c
The code is as follows:
package cimport "github.com/ggq89/mutualdep/a"type C struct { Vc int}func New(i int) *C { return &C{ Vc: i, }}func (c *C) Show() { a.Printf(c.Vc)}
package a
Dependent package b
and package c
, at the same time, dependent package b
package a
, package c
also dependent package a
.
main
The function code is as follows:
package mainimport "github.com/ggq89/mutualdep/a"func main() { a := a.New(3) a.Pb.DisplayC()}
At compile time, the error will be as follows:
import cycle not allowedpackage main imports github.com/ggq89/mutualdep/a imports github.com/ggq89/mutualdep/b imports github.com/ggq89/mutualdep/a
3. Defining the interface
Now the question is:
A depends on B B depends on A
For A struct
and B struct
with each other's pointers to this interdependence problem, you can use the method of defining the interface to solve the following steps:
package b
a interface
b
All the variables and methods used in the structure are a
translated into the method of using the interface, and the a
a interface
missing method is added in;
After the above steps are processed, the package b
code is as follows:
package bimport ( "github.com/ggq89/mutualdep/c")type B struct { Pa a}type a interface { GetC() *c.C}func New(a a) *B { return &B{ Pa:a, }}func (b *B) DisplayC() { b.Pa.GetC().Show()}
package a
complementary methods that may be missing in the process;
After processing, package a
the code in is as follows:
package aimport ( "fmt" "github.com/ggq89/mutualdep/b" "github.com/ggq89/mutualdep/c")type A struct { Pb *b.B Pc *c.C}func New(ic int) *A { a := &A{ Pc:c.New(ic), } a.Pb = b.New(a) return a}func (a *A)GetC() *c.C { return a.Pc}func Printf(v int) { fmt.Printf("%v", v)}
4. Splitting the package
Compile again with the following hints:
import cycle not allowedpackage main imports github.com/ggq89/mutualdep/a imports github.com/ggq89/mutualdep/b imports github.com/ggq89/mutualdep/c imports github.com/ggq89/mutualdep/a
Now is another interdependent issue:
A depends on C C depends on A
Unlike the previous interdependence, the preceding dependencies are A struct
B struct
caused by and have each other's pointers, which are hard interdependent;
And here is due to package c
methods in the method call package a
in the method, which belong to the soft mutual dependence;
- This interdependence can be solved by splitting the method into another package, and in the process of splitting the package, the method of the struct body may be transformed into a normal function;
Introduce package f
, migrate the method to f
medium:
package fimport "fmt"func Printf(v int) { fmt.Printf("%v", v)}
After the method package f
is moved, package a
the code is as follows:
package aimport ( "github.com/ggq89/mutualdep/b" "github.com/ggq89/mutualdep/c")type A struct { Pb *b.B Pc *c.C}func New(ic int) *A { a := &A{ Pc: c.New(ic), } a.Pb = b.New(a) return a}func (a *A) GetC() *c.C { return a.Pc}
package c
package f
It is changed to a call with the following code:
package cimport ( "github.com/ggq89/mutualdep/a/f")type C struct { Vc int}func New(i int) *C { return &C{ Vc: i, }}func (c *C) Show() { f.Printf(c.Vc)}
Now the dependencies are as follows:
At this point, both package dependencies are resolved.
5. Summary
For the soft mutual dependence, the use of subcontracting method can be solved, some functions caused by mutual dependence can only be solved by subcontracting, sub-package can refine the function of the package;
For the hard mutual dependence can only be solved by defining the interface, defining the interface can improve the independence of the package, and also improve the difficulty of tracking the code call relationship;
Reference article:
- Golang does not allow circular import issues ("Import cycle not Allowed"): http://ju.outofmemory.cn/entry/230115
- Golang a way to solve the import cycle not allowed: Https://studygolang.com/articles/10582?fr=sidebar
- Golang ("Import cycle not Allowed") Error: https://blog.csdn.net/skh2015java/article/details/53943784