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

Three structures are there: A(package a),B(package b),C(package c).

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 used an interface Ageter declared in another package i which has function declaration as GetA() *a.A Now I am using this interface Ageter in B and C through which I get instance of A and access functionality of C and B respectively.

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()
}

I should be able to use functionality of B in C and vice versa.

While building the code I am getting import cycle not allowed error. 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 Can anyone tell me how to fix this problem?

Thanks.

Go doesn’t allow import cycles to occur. If there are any import cycles detected, it throws a compile time error. Generally import cycles are considered as a bad design.

There are different approaches to solve this, for example you can use same package to describe all these 3 types in different 3 files:

package types

type A struct {
    B *b.B
    C *c.C
}

type B struct {
    o i.Ageter
}

type C struct {
    o i.Ageter
}

You're almost there, but I think you might be misunderstanding how you're supposed to use interfaces to fix a cyclic dependency. You've defined interfaces that directly reference the concrete types, so the dependency cycle is still there. Having i depend on a doesn't fix the problem, it just extends the cyclic dependency.

Let's get back to your core problem:

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.

You need to use your new package i to define interfaces only. Those interfaces should only reference each other - no references to A, B, or C. B and C should only reference the interface types in i - no references to A, B or C. Because of this, i must define interfaces for the necessary types in all 3 packages. For example:

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())
}