Как разрешить проблему импорта не допускается, хотя я использую интерфейс? - PullRequest
0 голосов
/ 10 января 2019

Есть три структуры: A(package a), B(package b), C(package c).

B хочет использовать функциональность C, а C хочет использовать функциональность B. У A есть экземпляры B и C, так что B может получить доступ к функциональности C через A и наоборот.

Я использовал интерфейс Ageter, объявленный в другом package i, который имеет объявление функции как GetA() *a.A Теперь я использую этот интерфейс Ageter в B и C, через который я получаю экземпляр 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()
}

Я должен иметь возможность использовать функциональность B в C и наоборот.

При создании кода я получаю 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 Может кто-нибудь сказать мне, как решить эту проблему?

Спасибо.

Ответы [ 2 ]

0 голосов
/ 10 января 2019

Вы почти у цели, но я думаю, что вы, возможно, неправильно поняли, как вы должны использовать интерфейсы для исправления циклической зависимости. Вы определили интерфейсы, которые напрямую ссылаются на конкретные типы , поэтому цикл зависимости все еще существует. Наличие i зависит от a не решает проблему, оно просто расширяет циклическую зависимость.

Давайте вернемся к вашей основной проблеме:

B хочет использовать функциональность C, а C хочет использовать функциональность B. A имеет экземпляры B и C, так что B может получить доступ к функциональности C через A и наоборот.

Вам необходимо использовать новый пакет 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())
}
0 голосов
/ 10 января 2019

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
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...