大家有没有见过没有使用依赖注入的复杂 Go 开源项目

21 小时 17 分钟前
 matrix1010

最近打算把公司的项目重构为使用依赖注入初始化所有服务(现在是每次需要某个依赖就内部 New 一个), 想找一些开源项目作为例子。但是简单找了找都是自动/手动进行依赖注入的,大家有没有见过 没有 使用依赖注入的:

4001 次点击
所在节点    Go 编程语言
84 条回复
kneo
21 小时 11 分钟前
一会儿有,一会儿没有,一会儿有没有。理解不了你的问题。
Nitroethane
21 小时 4 分钟前
看看这个,用 github.com/google/wire 实现的依赖注入: https://github.com/aquasecurity/trivy
matrix1010
20 小时 52 分钟前
注意我问的是 没有 使用依赖注入,因为使用依赖注入的太容易找。但调研肯定有和没有都包括才比较合适。另外应当是有一定复杂度的项目比如 grafana
aloxaf
20 小时 37 分钟前
第一眼也看成问「有哪些用了依赖注入的项目」

你都知道这种说法容易让人看错,为什么不换成更清晰的描述呢……
matrix1010
20 小时 33 分钟前
@aloxaf no, 我不知道 "这种说法容易让人看错", 只是可能大部分人的常识是"依赖注入用的很少,所以提问肯定是问哪些项目使用了依赖注入",基于这种常识无论怎么写都很容易看错
bthulu
20 小时 26 分钟前
都用 go 了, 就别用依赖注入了吧, 这一点都不 go.
V2April
20 小时 22 分钟前
大家有没有见过没有使用依赖注入的复杂 Go 开源项目 ×

大家有没有见过不使用依赖注入的复杂 Go 开源项目 √
nikenidage1
20 小时 22 分钟前
from GTP-4o

可以尝试改写为更加简洁且易于理解的表述方式,例如:

“大家见过哪些复杂的 Go 开源项目没有使用依赖注入吗?”
(直接以提问方式表达,语气更自然)
“有没有人见过不使用依赖注入的复杂 Go 开源项目?”
(改用“有没有人”开头,显得更口语化)
“大家有没有见过复杂的 Go 开源项目在代码中完全不用依赖注入?”
(强调“完全不用”,让语义更明确)
“复杂的 Go 开源项目中,有没有完全不使用依赖注入的例子?”
(将句子结构调整为陈述+提问,表达更清晰)
“大家知道哪些复杂的 Go 开源项目没有用依赖注入?”
(以“知道哪些”引导,强调寻找具体例子)
以上改写都可以根据具体语境选择使用,重点是让问题更明确直观,同时保持语气自然流畅。
matrix1010
20 小时 21 分钟前
@bthulu 这就没意思了兄弟,来点干货不要输出情绪。不 Go 为啥 wire, fx, samber/do 会存在
xiuming
20 小时 8 分钟前
@matrix1010 就是有人新语言 用旧思想写代码
fgwmlhdkkkw
20 小时 6 分钟前
整个全局指针不就行了吗……
sophos
20 小时 5 分钟前
rrfeng
20 小时 5 分钟前
k8s 有依赖注入吗?
xiuming
20 小时 4 分钟前
还要是理解 go 语言编程思想,Java 有 Java 编程思想没问题,可别把别的语言编程思想套到另一个语言,会很别扭很难受的。
sophos
20 小时 2 分钟前
哈哈哈,审错题了,不好意思
kuanat
19 小时 52 分钟前
我觉得需要重新描述一下,区分依赖注入和依赖注入框架。对 Go 来说,依赖注入几乎无处不在,但没有使用任何依赖注入框架的必要。

一时半会想不到特别合适的开源项目,我就尝试描述一下做法。正文里提到了依赖注入的两个场景,一个是被动初始化,另一个是单元测试。这两个都可以用接口 Interface 来完成,方法也是一样的。

标准库里有非常多传递实例的写法,比如传一个 *http.Client 这样。如果需要多个不同组件按照特定顺序初始化,可以直接用 struct embedding 把各个实例封装起来,然后就可以传递 struct 了。

因为我的组里有很多其他背景的开发者转型而来,对于传递 struct 的做法不认可,主要的理由是他们都有要初始化几十个依赖的经历。我对此的观点是,某个组件依赖几十个其他组件这件事本身就有问题,即便是真的有很多依赖,也只是依赖其中非常小的功能而非全部。我个人认为造成这种结果的原因是用基于 class 实现的继承去套用 Go ,而 Go 的做法是完全不实现继承功能,通过组合来抽象 OO 。

第二个需求单元测试需要对代码做调整,或者说对编程思路做调整。之前我在别的 Go 语言讨论帖子里反复引用过 Accept interfaces 这个说法,如果将调用方的代码依赖从实例改成接口,就可以非常简单地实现 mocking 来做单元测试。

因为调用方无须关心调用的是哪个实例,只要这个实例实现了特定的接口即可。将调用方的方法改写为接收接口,就可以用任意的实现来 mocking 对应的功能。

如果把接口当作继承来用,那自然就会觉得依赖是个复杂的事情,因为这个接口会越来越大,最终变成了模块之间的强耦合。实际上 Go 的思维里,接口越小越好,这里的思想是组合而非继承。一个非常小的接口是很容易 mocking 的。

另外如果观察一下 github 上 Go 的 DI/mocking 相关的项目也能发现一个趋势,相比其他语言这两种框架几乎都不流行。因为真的没有必要。不过反过来说,接口就是依赖注入。
houshuu
19 小时 48 分钟前
公司内部有不少,但是没有外网链接。体感 用 DI : 不用 DI = 7:3 的样子。

如果业务逻辑非常简单,依赖非常清晰,没有什么分岔的话,其实用不用 dig 写起来差不多的。个人经验来说依赖注入在 Go 大部分情况下都是伪需求或者说提升编码效率的小工具,开始的时候没用的话不必要强上。要跨组件公用的话,直接暴露一个变量或者一个 getter ,内部用 once 啥的初始化一下就行。

单元测试要补强的话,在写的时候就一定要习惯用 interface 来声明组件,方便之后 mock 。(当然另一个方面来说,Interface 写多了,用 DI 自动串起来还是挺方便的。)说实话每次写单元测试都感觉挺不 Go 的,还是 Java 那套思路。但是回头想想,非常多单元测试实际上没有任何作用,只是单纯提升 coverage 而已。现在我比较喜欢把核心逻辑去掉各种 side effect 抽到某个函数里,然后对函数做比较多的 UT ,其他 side effect 直接交给后面的 e2e 什么的来验证。还是要具体情况具体分析,避免无效工作。
matrix1010
19 小时 37 分钟前
@kuanat 几十个可能不多,但 初始化十几个个依赖 还是很容易出现的,特别是复杂度很高,多人协作,质量管理不太严格的大型项目上。只能接受而没法改变的情况下依赖注入框架就很方便。interface 方便单元测试 mock 是肯定的,我做的第一轮重构就是这个
matrix1010
19 小时 32 分钟前
@houshuu 其实只要你把依赖传入就是 DI ,不用 DI 的话就只能每次需要就 New 一个。在多人协作的情况下看似没用的单元测试有可能会在你意想不到的地方起作用
Jinnrry
18 小时 29 分钟前
1.我是 java 开发,曾经写了 2 年多的 java 项目
2.我是 go 开发,目前写了 5 年多的 go 项目
3.我接手过使用依赖注入的 go 项目,(就是楼上提到的 wire )

我们结论是,别总是用老思想写新代码,代码里面写个 new 有啥问题吗?既不影响性能又不影响可读性,搞个依赖注入,查问题的时候一脸懵逼,这函数哪里调用的,那对象哪里创建的。

我除了 java 和 go ,还写了几年 python ,php ,为啥其他语言都没有大面积流行依赖注入这一套?我觉得这足以说明这玩意没那么好。

虽然我以前也是写 java 的,但是我最怕的就是 go 项目打开一股 java 味,都换新语言了,学学新语言的主流编程方式吧,真别守着老一套了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1094915

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX