go語言依賴注入是什么-焦點速讀

          來源:php中文網 | 2023-01-18 17:58:58 |

          本教程操作環境:windows7系統、GO 1.18版本、Dell G3電腦。

          依賴注入是什么?

          第一次聽到這個詞的時候我是一臉懵逼的,很拗口有沒有,可能很多學過spring的同學覺得這是很基礎很好理解的知識,但因為我之前沒學過Java和spring,所以第一次接觸這個詞的時候是很懵的。

          依賴注入,英文名dependency injection,簡稱DI。依賴兩個字很好理解,在軟件設計上,從架構模塊到函數方法都存在大大小小的依賴關系。


          【資料圖】

          比如說在new A 之前需要先new B ,A依賴于B,這時候我們就可以說B是A的依賴,A控制B,AB之間存在著耦合的關系,而代碼設計思想是最好可以做到松耦合。如果某一天B需要改造那么A也需要跟著改造。這是一個依賴你可以覺得沒問題,但如果是A->B->C->D->E->F之間存在一連串的依賴關系,那么改造起來就會十分麻煩。

          這個時候就需要一種東西來解開他們之間的強耦合,怎么解耦呢,只能借助第三方力量了,我們把A對B的控制權交給第三方,這種思想就稱為控制反轉(IOC Inversion Of Control),這個第三方稱為IOC容器。而IOC容器要做的事情就是new一個B出來,然后把這個B的實例注入到A里面去,然后A就可以正常的使用基于B的方法了,這個過程被稱為依賴項注入,而基于IOC的這種方法就叫做依賴注入。

          簡單來說,依賴注入(DI)是一種解耦組件之間依賴關系的設計模式。在需要的時候,不同組件之間可以通過一個統一的界面獲取其它組件中的對象和狀態。Go語言的接口設計,避免了很多需要使用第三方依賴注入框架的情況(比如Java,等等)。我們的注入方案只提供非常少的類似Dager或Guice中的注入方案,而專注于盡量避免手動去配置對象和組件之間的依賴關系。

          依賴注入的好處

          明白了依賴注入的思想,應該也就明白了其帶來的最大好處——解耦。

          而解耦又能帶來更多的好處:代碼擴展性增強,代碼的可維護性增強,更容易進行單元測試等等。

          那么依賴注入如何實現呢?

          Java中有以下幾種方式:

          setter方法注入:實現特定屬性的public set方法,來讓外部容器調用傳入所依賴類型的對象。

          基于接口的注入:實現特定接口以供外部容器注入所依賴類型的對象。

          基于構造函數的注入:實現特定參數的構造函數,在新建對象時傳入所依賴類型的對象。

          基于注解的注入:在代碼里加上特定的關鍵字實現注入。

          注解是最常見的方式,它像注釋一樣不被當做代碼來執行,而是專門供別人閱讀。但注釋的讀者完全是人類,而注解的主要讀者除了人類之外還有框架或預編譯器。

          Go依賴注入-wire

          wire就是一種基于注解的依賴注入方式。wire是 Google 開源的一個依賴注入工具,我們只需要在一個特殊的go文件中告訴wire類型之間的依賴關系,它會自動幫我們生成代碼,幫助我們創建指定類型的對象,并組裝它的依賴。

          wire有兩個基礎概念,Provider(構造器)和Injector(注入器)。

          通過提供provider函數,讓wire知道如何產生這些依賴對象。wire根據我們定義的injector函數簽名,生成完整的injector函數,injector函數是最終我們需要的函數,它將按依賴順序調用provider

          wire的要求很簡單,新建一個wire.go文件(文件名可以隨意),創建我們的初始化函數。比如,我們要創建并初始化一個Mission對象,我們就可以這樣:

          //+build wireinjectpackage mainimport "github.com/google/wire"func InitMission(name string) Mission {  wire.Build(NewMonster, NewPlayer, NewMission)  return Mission{}}

          可以看到第一行的注解:+build wireinject,表示這是一個注入器。+build其實是 Go 語言的一個特性。類似 C/C++ 的條件編譯,在執行go build時可傳入一些選項,根據這個選項決定某些文件是否編譯。wire工具只會處理有wireinject的文件,所以我們的wire.go文件要加上這個。

          在函數中,我們調用wire.Build()將創建Mission所依賴的類型的構造器傳進去。例如,需要調用NewMission()創建Mission類型,NewMission()接受兩個參數一個Monster類型,一個Player類型。Monster類型對象需要調用NewMonster()創建,Player類型對象需要調用NewPlayer()創建。所以NewMonster()NewPlayer()我們也需要傳給wire

          寫完wire.go文件之后執行wire命令,就會自動生成一個wire_gen.go文件。

          // Code generated by Wire. DO NOT EDIT.//go:generate wire//+build !wireinjectpackage main// Injectors from wire.go:func InitMission(name string) Mission {  player := NewPlayer(name)  monster := NewMonster()  mission := NewMission(player, monster)  return mission}

          可以看到wire自動幫我們生成了InitMission方法,此方法中依次初始化了player,monster和mission。之后在我們的main函數中就只需調用這個InitMission即可。

          func main() {  mission := InitMission("dj")  mission.Start()}

          而在沒用依賴注入之前,我們的代碼是這樣的:

          func main() {  monster := NewMonster()  player := NewPlayer("dj")  mission := NewMission(player, monster)  mission.Start()}

          是不是簡潔了很多。這里只有三個對象的初始化,如果是更多可能才會意識到依賴注入的好處。

          比如:

          wire.go文件:// +build wireinject// The build tag makes sure the stub is not built in the final build.package diimport ("github.com/google/wire")//go:generate kratos t wirefunc InitApp() (*App, func(), error) {panic(wire.Build(dao.Provider, service.Provider, http.New, grpc.New, NewApp))}實現文件://daovar Provider = wire.NewSet(New, NewDB, NewRedis)//servicevar Provider = wire.NewSet(New, wire.Bind(new(pb.Server), new(*Service)))生成的wire_gen.go 文件:func InitApp() (*App, func(), error) {redis, cleanup, err := dao.NewRedis()if err != nil {return nil, nil, err}db, cleanup2, err := dao.NewDB()if err != nil {cleanup()return nil, nil, err}daoDao, cleanup3, err := dao.New(redis, db)if err != nil {cleanup2()cleanup()return nil, nil, err}serviceService, cleanup4, err := service.New(daoDao)if err != nil {cleanup3()cleanup2()cleanup()return nil, nil, err}engine, err := http.New(serviceService)if err != nil {cleanup4()cleanup3()cleanup2()cleanup()return nil, nil, err}server, err := grpc.New(serviceService)if err != nil {cleanup4()cleanup3()cleanup2()cleanup()return nil, nil, err}app, cleanup5, err := NewApp(serviceService, engine, server)if err != nil {cleanup4()cleanup3()cleanup2()cleanup()return nil, nil, err}return app, func() {cleanup5()cleanup4()cleanup3()cleanup2()cleanup()}, nil}

          所以,依賴注入到底是什么?

          封裝解耦罷了。

          以上就是go語言依賴注入是什么的詳細內容,更多請關注php中文網其它相關文章!

          關鍵詞: go語言 Golang 依賴注入

          亚洲美女自拍视频| 精品亚洲一区二区三区在线观看| 亚洲AV无码成H人在线观看| 久久久久久久尹人综合网亚洲| 国产亚洲精品岁国产微拍精品| 亚洲VA中文字幕无码毛片| 亚洲精品免费观看| 亚洲另类无码一区二区三区| 久久亚洲高清综合| 亚洲邪恶天堂影院在线观看| 亚洲国产精品精华液| 亚洲色大成网站WWW久久九九| 久久亚洲精品无码VA大香大香| 亚洲精品自偷自拍无码| 国产精品亚洲片在线| 亚洲一级毛片免费观看| 亚洲无线一二三四区手机| 久久久亚洲裙底偷窥综合| 色九月亚洲综合网| 亚洲小视频在线观看| 国产精品亚洲精品爽爽| 亚洲一级二级三级不卡| 国产精品久久久久久亚洲影视 | 亚洲欧洲日本在线| 亚洲高清最新av网站| 亚洲午夜久久久影院伊人| 亚洲欧洲另类春色校园网站| 亚洲最大av无码网址| 亚洲国产韩国一区二区| 亚洲精品第一综合99久久| 久久综合亚洲色HEZYO国产| 亚洲人成电影在线观看青青| 亚洲五月激情综合图片区| 精品国产日韩亚洲一区在线| 亚洲精品午夜国产VA久久成人| 亚洲中文字幕无码爆乳app| 国产日韩亚洲大尺度高清| 亚洲av乱码一区二区三区| 亚洲第一永久AV网站久久精品男人的天堂AV | 亚洲综合色自拍一区| 四虎亚洲精品高清在线观看|