What is a cyclic dependency

In fact, Package A introduces Package B, and then Package B introduces Package A, so circular dependency is formed.

The phenomenon is as follows:

The test code

package A

import (
	"strings"B/GoProject/main/gobase/cycle/B" ) func Foo(a string) (string) { return B.Add(a) } func Minus(a string) (string) { return strings.Trim(a, "\t")}Copy the code
package B

import A "GoProject/main/gobase/cycle/a"

func Goo(a string) (string) {
	return A.Minus(a)
}

func Add(a string) (string) {
	return a + "--"
}
Copy the code

Run the test code:

package cycle
import (
	"testing"

	A "GoProject/main/gobase/cycle/a"
)

func TestCycle(t *testing.T) {
	A.Foo("good")}Copy the code

Running result:

packageGoProject/main/gobase/cycle (test)
	imports /GoProject/main/gobase/cycle/a
	importsGoProject/main/gobase/cycle/b
	imports GoProject/main/gobase/cycle/a: import cycle not allowed
FAIL
Copy the code

Appearance pattern implementation

We introduced the appearance pattern earlier in the Java Design Pattern and found it useful when I first abstracted the methods in packages A and B into interfaces, isolating the methods first

package service

type A interface {
	Minus(s string) (string)
}

type B interface {
	Add(s string) (string)
}
Copy the code

Then I A and B implement the interface. For ease of processing, I will not define two structures.

package A

import (
	"strings"
	"github.com/hundred666/GoTest/service"
)

type AImpl struct {
	b service.B
}

func (a *AImpl) Foo(s string) (string) {
	return a.b.Add(s)
}

func (a *AImpl) Minus(s string) (string) {
	return strings.Trim(s, "\t")}Copy the code

The design of B is as follows:

package B

import "github.com/hundred666/GoTest/service"

type BImpl struct {
	a service.A
}

func (b *BImpl) Goo(a string) (string) {
	return b.a.Minus(a)
}

func (b *BImpl) Add(a string) (string) {
	return a + "--"
}
Copy the code

To implement the method, you need to be able to put the instantiated variables into A and B constructs respectively, so A needs to implement the following method

func NewA(a) *AImpl {
	return new(AImpl)
}
func (a *AImpl) SetB(b service.B) {
	a.b = b
}
Copy the code

B The following methods are required

func NewB() *BImpl {
	return new(BImpl)
}

func (b *BImpl) SetA(a service.A) {
	b.a = a
}
Copy the code

You can call it when you need to

package main

import (
	"github.com/hundred666/GoTest/B"
	"github.com/hundred666/GoTest/A"
	"fmt"
)

func main() {
	b := B.NewB()
	a := A.NewA()
	a.SetB(b)
	r := a.Foo("aa")
	fmt.Println(r)
}
Copy the code

The resources

  • ​Zhuanlan.zhihu.com/p/326112287…
  • Segmentfault.com/a/119000003…