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

标签 go interface

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

B 想要使用C 的功能,C 想要使用B 的功能。 ABC 实例,所以 B 可以访问 C 的功能> 通过 A 反之亦然。

我使用了在另一个 package i 中声明的接口(interface) Ageter,它的函数声明为 GetA() *a.A 现在我在 BC 中使用这个接口(interface) 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 错误。 不允许导入循环 包主 导入基础知识/importCycleIssue/issueFix/a 导入基础知识/importCycleIssue/issueFix/b 导入基础知识/importCycleIssue/issueFix/i 导入基础知识/importCycleIssue/issueFix/a 谁能告诉我如何解决这个问题?

谢谢。

最佳答案

您快完成了,但我认为您可能误解了应该如何使用接口(interface)来修复循环依赖性。您已经定义了直接引用具体类型 的接口(interface),因此依赖循环仍然存在。让 i 依赖于 a 并不能解决问题,它只是扩展了循环依赖。

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

B wants to use functionality of C and C wants to use functionality of B. A has both B and C instances, so that B can access functionality of C via A and vice versa.

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

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 - 如何解决导入周期不允许的问题,尽管我正在使用界面?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54130194/

相关文章:

java - 如何引用 Java 中接口(interface)实现的类类型?

java - Java中如何用接口(interface)替换抽象类?

go - 如何在 Golang 中将 [4]byte{1,2,3,4} 转换为 "1.2.3.4"?

pointers - 不使用 reflrect 打印类型并创建新对象

go - 处理url "/foobar/"替换css <link>, js &lt;script&gt; 路径以 "/foobar/"开头

interface - go中能够包含任意类型的数据结构是什么?

c# - 不确定何时在 C# 中使用 'base'

go - 在 go 中输入断言

go - 使用zap时如何自定义日志格式?

java - 为什么 scala.Serializable 不指定任何方法?