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…