好好爱自己!

【转】Is there a better dependency injection pattern in golang?

 https://coolshell.cn/articles/9949.html

 https://dotblogs.com.tw/daniel/2018/01/17/140435

 

https://github.com/golobby/container

 

https://blog.drewolson.org/dependency-injection-in-go

https://quii.gitbook.io/learn-go-with-tests/go-fundamentals/mocking

 

---------------------

案例解釋:

小明是個愛乾淨的人,但他工作時常加班導致房間雜亂,他不能忍受此狀況,所以小明去找一個清潔阿姨每天幫忙他打掃家裡

 

哪天阿姨哪天有事不能打掃,小明就必須要再去找人來幫忙打掃,由此可知小明耦合阿姨

------------------------------------------------------------------------------------

 

如果今天是....

小明把他要的條件給「打掃仲介公司」,仲介公司幫他尋找有沒有符合小明需求的打掃阿姨,假如今天A阿姨請假了,仲介公司會自動找另一個符合需求B阿姨幫忙打掃...

 

原本小明需耦合於打掃阿姨,現在被「仲介公司」做了控制反轉讓「仲介公司」來提供打掃阿姨。

小明不用管是否今天有人會來打掃,「仲介公司」會幫小明找到一個掃地阿姨。

 

「仲介公司」可看作 依賴注入容器
「小明」可看作 被動接收物件

「打掃阿姨」可看作 被依賴物件

 

在使用IOC容器前需先了解雙方的依賴關係(誰依賴誰?)

 

上述還有一個很重要的觀念是,依賴和被接收對象要倚賴抽象。

 

 

範例使用:VS2015

IOC容器:AutoFac

下面範例來說明上面的例子

 

小明自己依賴於掃地阿姨

依賴程式碼寫在小明類別內部日後要更改只能動內部程式碼。

/// <summary>
/// 小明直接依賴 Aunt 不是依賴抽象
/// 日後要改必須動內部
/// </summary>
public class Mine
{
    public Aunt aunt = new Aunt();

    public void Room()
    {
        aunt.Swapping();
    }
}

 

呼叫使用時

Mine mine = new Mine();
mine.Room();

 

小明找仲介公司
 

仲介公司(Ioc容器)

在仲介公司內註冊需求,讓仲介公司日後幫你找人(註冊的類別)

/// <summary>
/// 仲介公司
/// </summary>
/// <returns></returns>
private static IContainer MiddleCompany()
{
    ContainerBuilder builder = new ContainerBuilder();

    //在仲介公司裡寫需求人申請單
    builder.RegisterType<MineWithMiddle>();
    //小明所需打掃阿姨需求
    builder.RegisterType<Aunt>().As<ISwapable>();

    return builder.Build();
}

 

使用起來

IContainer middleCompany = MiddleCompany();
//仲介公司(IOC AutoFac)自動幫小明注入一個打掃阿姨
MineWithMiddle mineWithMiddle = middleCompany.Resolve<MineWithMiddle>();

mineWithMiddle.Room();

 

總結:

  1. 系統中模組建議依賴抽象,因為各個模組間不需要知道對方太多細節(實作),知道越多耦合越強。
    像網頁瀏覽器和伺服器是依賴Http協議,用戶端不管是手機.電腦,平板,伺服器端php,asp.net,java都可互相交信,依賴Http協議共用的合約
  2. 控制反轉:是一個設計思想 ,把對於某個物件的控制權移轉給共同第三方
  3. 依賴注入:把被依賴物件注入被動接收物件中


範例原始碼 :https://github.com/isdaniel/IOC_Sample

參考連結 : http://www.cnblogs.com/xdp-gacl/p/4249939.html

----------------------

 

 

 

 

-------

Asked 6 years ago
Modified 5 months ago
Viewed 62k times
50

Given this code:

package main

import (
    "fmt"
)

type datstr string

type Guy interface {
   SomeDumbGuy() string
}

func (d *datstr) SomeDumbGuy() string {
  return "some guy"
}

func someConsumer(g Guy) {
  fmt.Println("Hello, " + g.SomeDumbGuy())
}

func main() {
    var d datstr
    someConsumer(&d)
}

Is the wiring of components together that's done in main the right way to wire a dependency together? It seems like I'm over using this a bit in my code. Is there a common pattern better than this, or am I overthinking it?

 
  • 4
    Bit of an opinion-based question, but that's the style I personally prefer. Unexported struct, exported interface, struct stored by pointer in the interface. Makes mocking and middleware wrapping super easy, and is better aligned to an object-oriented abstraction principle than exported structs. Only addition I might make is a factory function for the datastr type that returns a Guy interface, as this gives a compile-time guarantee that your structure fulfills the interface it is expected to fulfill. 
    – Kaedys
     Jan 27, 2017 at 18:24 
  • 1
     
     
     

    The best practice is not to use a DI library. Go is meant to be a simple language that is easy to follow. A DI library/framework will abstract that away from you (and to some extent make DI magical).

     
    • 6
      Unfortunately haven't used wire and neither am i an expert in DI in Golang. However, i strongly believe that no specific pattern is needed since any library would complicate the program flow and Golang aims to be a language which does not have any magic and is easy to follow. 
      – Zeeshan
       Mar 3, 2020 at 4:18
    • 54
      If this is classed as the best practice, please add a Go doc reference to that effect. Considering that Google created wire as a DI system that avoids reflection and maintains the calling clarity I find this answer more likely to be incorrect. 
      – Jeremy
       Feb 18, 2021 at 17:36
    • 2
      No Go Doc reference; have myself read a bunch of articles and effective go. Using no DI framework is more idiomatic Go compared to using a DI framework that does reflection or magic under the hood. 
      – Zeeshan
       Mar 18, 2021 at 5:40
    • 11
      Says who? I've seen quite a few good projects that were using some sort of DI. Also Google with its Wire would argue with your statement...   Apr 17, 2021 at 23:47
    •  
      Is only I think this DI thing is squalid (by adding a new function variable?) And that why testing looks like shit) For example, I have a service who do some little logic and send a request to Google Translate API, this service is used by another service, why for the testing parent service need to know all about children service dependencies and insert them into function as params - It confuses me   Oct 26, 2021 at 5:57
    • 3
      Go allows you to make library that does DI. Abstraction is needed to some degree. Just follow DRY and KISS principle. There is no such thing as best practice to not use XYZ libraries. Unless your team abused it. IMHO. 
      – rhzs
       Jan 1, 2022 at 10:18
    • 2
      Anyone coming from an enterprise programming world would not argue that DI should not be used. This is definitely not a best practice, in contrast this is unmaintainable. Any serious server project with more than 5 files would result in manually written wiring code. Using something like Googles Wire makes it much easier. A simple language should not have the goal to stick to a novice level of programmers. 
      – k_o_
       Jul 5, 2022 at 13:00
    • 2
      Still don't know why this answer was selected. It mixed two different things, language specifications, and programming patterns. In essence, it doesn't answer the original question it's just the author's opinion.   Jul 14, 2022 at 11:45
    • 1
      Go's simplicity as a language does not mean it should only be used to write simple applications. As an app becomes more complex, a "DI is too complex for Go" mindset will quickly lead to "my Go app's init code is getting hard to maintain", and from there to "my application is too complex for Go" -- at which point you are forced to switch languages. This cannot be the correct stance; in the long term it will harm the Go community/ecosystem. Dependency injection can be done cleanly, with compile-time safety and without reflection (as in Google's Wire) if that's your preference.   Aug 25, 2022 at 19:35
       
       

      Google's Wire looks promising. There're some articles about it:

       

      Uber's Dig is pretty awesome. Here's a great blog post about it: Dependency Injection in Go

       

       

      --------------------------------------------------------------------------------

Ioc是一個oop重要的程式設計思想。 此文帶著大家初探 IOC(控制反轉) , DI(依賴注入) ~~ 學一個技術或思想前我們最好先了解,這個技術或思想為我們解決怎樣問題。 Ioc—Inversion of Control 控制反轉 控制反轉是一個設計思想 ,把對於某個物件的控制權移轉給第三方容器 簡單解釋 A物件程式內部需要使用B物件 A,B物件中有依賴的成份 控制反轉是把原本A對B控制權移交給第三方容器 降低A對B物件的耦合性,讓雙方都倚賴第三方容器。 反轉概念如下圖 我們可發現有兩點差異 使用者原本直接耦合於A,但使用IoC容器使用者就直接對容器而不是A 至於A關連於誰由容器決定 原本A直接控制於B,C,但透過一個IoC容器我們控制權反轉給了容器 IoC經典實現對象設計法則 好萊塢法則:“別找我們,我們找你” 系統中模組建議依賴抽象,因為各個模組間不需要知道對方太多細節(實作),知道越多耦合越強。 DI—Dependency Injection 依賴注入 把被依賴物件注入被動接收物件中 案例解釋: 小明是個愛乾淨的人,但他工作時常加班導致房間雜亂,他不能忍受此狀況,所以小明去找一個清潔阿姨每天幫忙他打掃家裡 哪天阿姨哪天有事不能打掃,小明就必須要再去找人來幫忙打掃,由此可知小明耦合阿姨 ------------------------------------------------------------------------------------ 如果今天是.... 小明把他要的條件給「打掃仲介公司」,仲介公司幫他尋找有沒有符合小明需求的打掃阿姨,假如今天A阿姨請假了,仲介公司會自動找另一個符合需求B阿姨幫忙打掃... 原本小明需耦合於打掃阿姨,現在被「仲介公司」做了控制反轉讓「仲介公司」來提供打掃阿姨。 小明不用管是否今天有人會來打掃,「仲介公司」會幫小明找到一個掃地阿姨。 「仲介公司」可看作 依賴注入容器 「小明」可看作 被動接收物件 「打掃阿姨」可看作 被依賴物件 在使用IOC容器前需先了解雙方的依賴關係(誰依賴誰?) 上述還有一個很重要的觀念是,依賴和被接收對象要倚賴抽象。 範例使用:VS2015 IOC容器:AutoFac 下面範例來說明上面的例子 小明自己依賴於掃地阿姨 依賴程式碼寫在小明類別內部日後要更改只能動內部程式碼。 /// /// 小明直接依賴 Aunt 不是依賴抽象 /// 日後要改必須動內部 /// public class Mine { public Aunt aunt = new Aunt(); public void Room() { aunt.Swapping(); } } 呼叫使用時 Mine mine = new Mine(); mine.Room(); 小明找仲介公司 仲介公司(Ioc容器) 在仲介公司內註冊需求,讓仲介公司日後幫你找人(註冊的類別) /// /// 仲介公司 /// /// private static IContainer MiddleCompany() { ContainerBuilder builder = new ContainerBuilder(); //在仲介公司裡寫需求人申請單 builder.RegisterType(); //小明所需打掃阿姨需求 builder.RegisterType().As(); return builder.Build(); } 使用起來 IContainer middleCompany = MiddleCompany(); //仲介公司(IOC AutoFac)自動幫小明注入一個打掃阿姨 MineWithMiddle mineWithMiddle = middleCompany.Resolve(); mineWithMiddle.Room(); 總結: 系統中模組建議依賴抽象,因為各個模組間不需要知道對方太多細節(實作),知道越多耦合越強。 像網頁瀏覽器和伺服器是依賴Http協議,用戶端不管是手機.電腦,平板,伺服器端php,asp.net,java都可互相交信,依賴Http協議共用的合約 控制反轉:是一個設計思想 ,把對於某個物件的控制權移轉給共同第三方 依賴注入:把被依賴物件注入被動接收物件中 範例原始碼 :https://github.com/isdaniel/IOC_Sample 參考連結 : http://www.cnblogs.com/xdp-gacl/p/4249939.html
posted @ 2023-02-06 18:51  立志做一个好的程序员  阅读(48)  评论(0编辑  收藏  举报

不断学习创作,与自己快乐相处