【问题标题】:how to resolve import cycle not allowed issue, though I am using interface?尽管我使用的是界面,但如何解决导入周期不允许的问题?
【发布时间】:2019-06-05 09:53:17
【问题描述】:

共有三个结构:A(package a),B(package b),C(package c)

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

我使用了在另一个package i 中声明的接口Ageter,其函数声明为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 谁能告诉我如何解决这个问题?

谢谢。

【问题讨论】:

标签: go interface


【解决方案1】:

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
}

【讨论】:

    【解决方案2】:

    你快到了,但我认为你可能误解了你应该如何使用接口来修复循环依赖。您已经定义了直接引用具体类型的接口,因此依赖循环仍然存在。让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())
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-12
      • 2023-03-13
      • 1970-01-01
      • 1970-01-01
      • 2022-07-02
      • 2022-11-02
      • 2019-07-18
      • 1970-01-01
      相关资源
      最近更新 更多