如何解决不允许导入周期的问题,尽管我正在使用界面?



有三种结构:A(package a)B(package b)C(package c)

B想要使用C的功能,C想要使用B的功能。A同时具有BC实例,因此B可以通过A访问C的功能,反之亦然。

我使用了一个接口Ageter在另一个package i中声明,该接口的函数声明为GetA() *a.A现在我在BC中使用这个接口Ageter,通过它我分别获得A实例和访问CB的功能。

package a
import (
"fmt"
"basics/importCycleIssue/issueFix/b"
"basics/importCycleIssue/issueFix/c"
)
type A struct {
B *b.B
C *c.C
}
var a = NewA()
func NewA() *A {
a := &A{}
a.B = b.NewB(a)
a.C = c.NewC(a)
return a
}
func GetA() *A{
return a
}
---------------------------------------------------
package b
import (
"fmt"
"basics/importCycleIssue/issueFix/i"
)
type B struct {
o i.Ageter
}
func NewB(o i.Ageter) *B {
b := &B{o: o}
return b
}
func (b *B) UseC() {
fmt.Println("need to use C:",b.o.GetA().C)
}
----------------------------------------------------
package c
import (
"fmt"
"basics/importCycleIssue/issueFix/i"
)
type C struct {
o i.Ageter
}
func NewC(o i.Ageter) *C {
c := &C{o: o}
return c
}
func (c *C) UseB() {
fmt.Println("need to use B:",c.o.GetA().B)
}
----------------------------------------------------
package i
import (
"basics/importCycleIssue/issueFix/a"
)
type Aprinter interface {
PrintA()
}
type Ageter interface {
GetA() *a.A
}
---------------------------------------------------
package main
import (
"basics/importCycleIssue/issueFix/a"
)
func main() {
o := a.NewA()
o.B.UseC()
o.C.UseB()
}

我应该能够在C中使用B的功能,反之亦然。

在构建代码时,我收到import cycle not allowed错误。 import cycle not allowed package main imports basics/importCycleIssue/issueFix/a imports basics/importCycleIssue/issueFix/b imports basics/importCycleIssue/issueFix/i imports basics/importCycleIssue/issueFix/a 谁能告诉我如何解决这个问题?

谢谢。

你快到了,但我认为你可能误解了你应该如何使用接口来修复循环依赖关系。你已定义直接引用具体类型的接口,因此依赖项周期仍然存在。i依赖a并不能解决问题,它只是扩展了循环依赖。

让我们回到你的核心问题:

B 想要使用 C 的功能

,C 想要使用 B 的功能。A 同时具有 B 和 C 实例,因此 B 可以通过 A 访问 C 的功能,反之亦然。

您只需要使用新的包i来定义接口。这些接口应相互引用 - 不引用 A、B 或 C.B 和 C 应引用 i 中的接口类型 -引用 A、B 或 C。因此,我必须在所有 3 个包中为必要的类型定义接口。例如:

package i
import (
)
type A interface {
GetB() B
GetC() C
}
type B interface {
UseC()
}
type C interface {
UseB()
}
---------------------------------------------------
package a
import (
"fmt"
"basics/importCycleIssue/issueFix/b"
"basics/importCycleIssue/issueFix/c"
"basics/importCycleIssue/issueFix/i"
)
type A struct {
B *b.B
C *c.C
}
func NewA() *A {
a := &A{}
a.B = b.NewB(a)
a.C = c.NewC(a)
return a
}
// These methods implement i.A and return the i.B and i.C interface types
func (a A) GetB() i.B {
return a.B
}
func (a A) GetC() i.C {
return a.C
}
---------------------------------------------------
package b
import (
"fmt"
"basics/importCycleIssue/issueFix/i"
)
type B struct {
a i.A
}
func NewB(a i.A) *B {
b := &B{a: a}
return b
}
func (b *B) UseC() {
fmt.Println("need to use C:",b.a.GetC())
}
----------------------------------------------------
package c
import (
"fmt"
"basics/importCycleIssue/issueFix/i"
)
type C struct {
a i.A
}
func NewC(a i.A) *C {
c := &C{a: a}
return c
}
func (c *C) UseB() {
fmt.Println("need to use B:",c.a.GetB())
}

Go 不允许发生导入循环。如果检测到任何导入周期,则会引发编译时错误。通常,导入周期被认为是一个糟糕的设计。

有不同的方法可以解决这个问题,例如,您可以使用同一个包在不同的 3 个文件中描述所有这些 3 种类型:

package types
type A struct {
B *b.B
C *c.C
}
type B struct {
o i.Ageter
}
type C struct {
o i.Ageter
}

最新更新