【问题标题】:Package decoupling in gogo中的包解耦
【发布时间】:2018-03-02 20:53:02
【问题描述】:

我们都知道依赖注入使包解耦。 但是我对 go 中依赖注入的最佳实践有点困惑。
让我们假设包用户需要访问配置包。
我们可以将 Config 对象传递给 User 方法。这样,只要新代码解析接口,我就可以更改 Config 包功能。 另一种方法是直接调用 Config 包方法,在这种情况下,只要方法名称保持不变,我也可以更改 Config 代码。像这样

更新:

这两种方法有什么不同:

package User

func foo(config ConfigObject) {
   config.Foo()
}

还有这个:

package User

import Config

func foo() {
   config.Foo()
}

【问题讨论】:

    标签: go design-patterns dependency-injection solid-principles decoupling


    【解决方案1】:

    在方法的config 参数上调用config.Foo 意味着您收到某个结构的实例(可能实现接口Config)并在该实例/接口上调用方法Foo。将其视为在 OO 术语中调用对象的方法:

    package user
    
    func foo(cfg config.Config) {
       cfg.Foo()
    }
    

    在导入config 包后调用config.Foo 意味着您正在调用包config 的函数Foo,而不是任何对象/结构/接口。将其视为没有任何对象的纯过程编程:

    package user
    
    import config
    
    func foo() {
       config.Foo()
    }
    

    后者与依赖注入无关,如果Config是一个接口,前者可能构成其中的一部分。

    另一方面,依赖注入在 Go 中遵循与其他语言相同的规则:

    接受接口,提供实现

    因为在 Go 中,结构隐式而不是显式地满足接口(Java 就是这种情况)

    • 接受值的代码只需要知道接口并导入即可;
    • 实现它的代码甚至不需要了解接口(它可能恰好满足它);
    • 将 impl 提供到接受 界面显然需要两者都知道。

    对于您的示例,这意味着:

    package config
    
    type Config interface {
        Foo() string
    }
    
    package foo
    
    type Foo struct{}
    
    func (f *Foo) Foo() string {
        return "foo"
    }
    
    package boo
    
    type Boo struct{}
    
    func (b *Boo) Foo() string {
        return "boo" 
    }
    
    package main
    
    func foo(cfg config.Config) string{
        return cfg.Foo()
    }
    
    func main() {
        // here you inject an instance of Foo into foo(Config)
        
        log.Print(foo(&foo.Foo{}))
    
        // here you inject an instance of Boo into foo(Config)
        log.Print(foo(&boo.Boo{})
    }
    

    打印

    2018/03/03 13:32:12 富

    2018/03/03 13:32:12 嘘

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-01-30
      • 1970-01-01
      • 2013-09-14
      • 2013-06-09
      • 1970-01-01
      • 2013-04-04
      • 1970-01-01
      相关资源
      最近更新 更多