我来自node.js和nest.js世界,其中DI很简单并且由框架提供。在构建Go服务时我可以或者应该考虑使用依赖注入吗?
是的,在 Go 中这是可能的。
Go 的简单三步 DI 系统:
假设您有一个包 A,它不会导入包 B,但会调用该包中的一些函数;例如,函数 Load() 和 Save()。
type Storage interface {
Load(string) []byte
Save(string, []byte)
}
包 A 中的类型可以引用该接口并调用 Load() 和 Save(),而无需知道这些调用的实际接收者。
type StructA struct {
content []byte
storage Storage
}
func NewStructA(s Storage) *StructA {
return &StructA{
content: ...,
storage: s,
}
}
func (a *StructA) Save(name string) {
a.storage.Save(name, a.content)
}
func (a *StructA) Load(name string) {
a.content = a.storage.Load(name)
}
type StoreB struct {
poem []byte
}
func (b *StoreB) Save(name string, contents []byte) {
// let's say StoreB contains a map called data
b.data[name] = contents
}
func (b *StoreB) Load(name string) []byte {
return b.data[name]
}
main
中,连接电线。storage := B.StructB
a := A.NewStructA(storage)
a.Save()
现在您可以添加其他存储设备(包 C、D、...)并将它们连接到
main
。
storage2 := C.StructC
a2 := A.NewStructA(storage2)
a2.Save()
更详细的讨论在这里:https://appliedgo.net/di/
基于依赖注入的 Go 应用程序框架。 https://github.com/uber-go/fx
Go 的基于反射的依赖注入工具包。 https://github.com/uber-go/dig
是的,你应该考虑 Go 中的 DI,DI 在 Go 中具有与任何其他语言相同的优势。在go中使用接口就可以轻松实现。
由于Golang中对一流函数的支持,DI可以通过函数式编程方法来实现。当函数初始化延迟并相互传递上下文时。
类似于 Reader monad,这是函数式编程世界中 DI 的流行方式。
如果你已经来自 Node.js/Nest.js 世界,也许你可以知道 fp-ts Reader monad
我为Golang实现了函数式编程上下文库,也许它对FP风格的DI有用,这主要是受到Reader monad的启发。