GOLANG 中 解决 循环依赖(相互引用) 的 理解
循环依赖 本质上一个错误的设计,在go里面,直接把它作为了一个编译时的错误。
什么是循环依赖呢?
假如有 一个结构体 A 和 一个结构体B,A 和 B 分别在包a和包b中, 而且结构体A 依赖 结构体B, 并且结构体B 依赖结构体A, 如果写成这样就会导致 循环依赖 或者说是 循环导入。
这是a的代码
package a import ( "fmt" "my-test/importcicle/b" ) type A struct {} func (a A) DoSomethingWithA() { fmt.Println(a) } func CreateA() *A { a := &A{} return a } func invokeSomethingFromB() { o := b.CreateB() o.DoSomethingWithB() }
这是b的代码
package b import ( "fmt" "my-test/importcicle/a" ) type B struct {} func (b B) DoSomethingWithB() { fmt.Println(b) } func CreateB() *B { b := &B{} return b } func invokeSomethingFromA() { o := a.CreateA() o.DoSomethingWithA() }
正如上面的代码,A需要B,B也需要A,这样就导致了循环导入或者说循环依赖。当你要编译这段代码时,会报错:
import cycle not allowed
package my-test/importcicle
imports my-test/importcicle/a
imports my-test/importcicle/b
imports my-test/importcicle/a
解决方法
通常为了避免这种循环依赖,可以在一个新的package中引入一个接口,比如新建一个 package 叫 x,这个interface中包含有B依赖A结构中所有的方法。
package x type ADoSomethingIntf interface { DoSomethingWithA() }
现在修改b包中的代码,导入x, 而不是导入a
import ( "fmt" "my-test/importcicle/x" ) type B struct {} func (b B) DoSomethingWithB() { fmt.Println(b) } func CreateB() *B { b := &B{} return b } // 注意 这里稍微做了些调整 func invokeSomethingFromA(o x.ADoSomethingIntf) { o.DoSomethingWithA() }
但是如果仍然需要A的实例,那怎么办呢?
所以将不得不引入另外一个 package 比如说 y,y将同时导入a和b,它创建了A的一个实例并将它传递给b。
import ( "my-test/importcicle/a" "my-test/importcicle/b" ) func doSomethingWithY() { o := &a.A{} b.InvokeSomethingFromA(o) }
这就是我解决循环依赖的方式,总结就是:
A依赖于B
B依赖于X
Y依赖于A和B
因此没有循环依赖
摘自:https://zhuanlan.zhihu.com/p/326112287
参考:https://www.coder.work/article/207743
后注:
今天遇到这样一种情况:
* 初始化一个对象A,需要用到对象 B
* 初始化一个对象B,需要用到对象 A
譬如:A 是log; B 是 config
初始化 A 需要从 B 对象中读取 log 的配置,同时又想在 B 中加载配置时,打印 log ,刚开始还以为他NND是循环引用,这他么是逻辑错误好不好!错误好不好!错误!!
扯远了,还说循环引用:
其实循环引用就是,A想要的方法正好在B中,B想要的方法正好在A中,只此而已。不能再牵扯太多了。并且这两个方法没有交集,两个对象的创建也没有交集。
所以解决循环引用的核心就两点:
使用接口
放到不同包中
所有说叫他 循环依赖 有点太不恰当了,麻蛋的
共 0 条评论