• Ukieweb

    佳的博客

    曾梦想仗剑天涯,后来工作忙没去。

GOLANG 中 解决 循环依赖(相互引用) 的 理解

循环依赖 本质上一个错误的设计,在go里面,直接把它作为了一个编译时的错误

什么是循环依赖呢?

假如有 一个结构体 A 一个结构体BAB 分别在包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
0
下一篇:关于 浏览器 自动下载 图标 favicon.ico 的设置

0 条评论

老佳啊

85后,大专学历,中原人士,家里没矿。

由于年轻时长的比较帅气,导致在别人眼里,我一直不谈恋爱的原因是清高,实则是自己的小自卑。最大的人生目标就是找一个相知相爱相容的人,共度余生。

和人相处时如果能感受到真诚,会非常注重彼此的关系,对别人没有什么心机,即使有利益冲突,一般也会以和为贵,因为在这个世界上,物质的东西,从来不会吸引到我。

特别迷恋那些大山大水,如果现在还能隐居,可能早就去了。对那些宏伟的有底蕴的人文景观比较不感冒。

从事于IT行业,却一直对厨房念念不忘,由于身材魁梧,总觉得自己上辈子是个将军,可惜这辈子没当兵,也不会打架。