有三种结构:A(package a)
、B(package b)
、C(package c)
。
B
想要使用C
的功能,C
想要使用B
的功能。A
同时具有B
和C
实例,因此B
可以通过A
访问C
的功能,反之亦然。
我使用了一个接口Ageter
在另一个package i
中声明,该接口的函数声明为GetA() *a.A
现在我在B
和C
中使用这个接口Ageter
,通过它我分别获得A
实例和访问C
和B
的功能。
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
}