Go 依賴注入庫wire基本使用
前言
學(xué)習(xí)過Java 開發(fā)的同學(xué),一定對依賴注入有所耳聞。依賴注入(Dependency Injection,簡稱 DI)是一種設(shè)計模式,通過將組件依賴項外部化,使代碼更加模塊化和易于測試。對于Wire的使用,可以使得開發(fā)人員不用在手寫對應(yīng)實例的創(chuàng)建,只需要規(guī)范化的編寫對應(yīng)的依賴代碼,并通過wire gen 對應(yīng)目錄即可生成對應(yīng)的實例創(chuàng)建代碼。
一、什么是依賴注入
依賴注入是一種設(shè)計模式,用于將對象的依賴關(guān)系通過構(gòu)造函數(shù)、方法或?qū)傩宰⑷?,而不是在對象?nèi)部創(chuàng)建依賴。這樣可以提高代碼的可測試性和靈活性。
1 舉個栗子
比如在Web開發(fā)中,常用的一些設(shè)計模式,都會將業(yè)務(wù)分層多個層去處理,比如MVC結(jié)構(gòu),在Controller層就要調(diào)用Service層的業(yè)務(wù),而Service層又需要dao。這種存在依賴的關(guān)系,在創(chuàng)建實例時,不是在內(nèi)部創(chuàng)建,而是通過注入就是依賴注入。
package main
import "fmt"
type Dao struct {
}
func NewDao() *Dao {
return &Dao{}
}
func (d *Dao) Do() {
fmt.Println("do dao")
}
// 實現(xiàn)接口的結(jié)構(gòu)體
type Service struct {
dao *Dao
}
func NewService(dao *Dao) *Service {
return &Service{
dao: dao,
}
}
func (s *Service) Execute() {
fmt.Println("Executing service...")
s.dao.Do()
}
// 使用依賴注入的結(jié)構(gòu)體
type Controller struct {
service *Service
}
func NewController(s *Service) *Controller {
return &Controller{service: s}
}
func (c *Controller) Run() {
c.service.Execute()
}
func main() {
daoDao := dao.NewDao()
serviceService := service.NewService(daoDao)
controllerController := controller.NewController(serviceService)
controller.Run()
}如上述代碼中的main函數(shù)中的內(nèi)容就是依賴注入的形式
dao := NewDao() service := NewService(dao) // service 通過傳入的方式進(jìn)入到Controller中,而不是內(nèi)部創(chuàng)建 controller := NewController(service) controller.Run()
2. 依賴注入的好處
依賴注入的好處包括:
- 可測試性:可以輕松替換依賴,進(jìn)行單元測試。
- 解耦合:減少模塊之間的直接依賴,增強(qiáng)代碼靈活性。
- 易于維護(hù):更改依賴時無需修改使用它的代碼。
- 可復(fù)用性:相同的依賴可以在多個地方使用,提高代碼復(fù)用性。
- 更清晰的代碼結(jié)構(gòu):依賴注入有助于明確對象之間的關(guān)系,使得代碼結(jié)構(gòu)更加清晰,易于理解。
二、Wire
Wire 是一個專為依賴注入(Dependency Injection)設(shè)計的代碼生成工具,它可以自動生成用于初始化各種依賴關(guān)系的代碼,從而幫助我們更輕松地管理和注入依賴關(guān)系。
1.使用wire的前置條件
使用wire需要兩個前置條件:
- wire命令安裝
- golang中使用 wire 提供者生成函數(shù)
安裝wire命令
go install github.com/google/wire/cmd/wire@latest
代碼導(dǎo)入wire
使用 Go 的包管理工具安裝 Wire:
go get github.com/google/wire
創(chuàng)建Wire生成函數(shù)
// +build wireinject
package main
import "github.com/google/wire"
func InitializeController() *Controller {
wire.Build(NewMyService, NewController)
return &Controller{}
}2.小試牛刀
剛才main中的代碼,分別拆分出來,這樣更符合實際的開發(fā)場景。
├─controller ├─dao ├─service └─wiretest

每個部分的代碼
controller/controller.go
package controller
import "wirelearn/service"
// 使用依賴注入的結(jié)構(gòu)體
type Controller struct {
service *service.Service
}
func NewController(s *service.Service) *Controller {
return &Controller{service: s}
}
func (c *Controller) Run() {
c.service.Execute()
}dao/dao.go
package dao
import "fmt"
type Dao struct {
}
func NewDao() *Dao {
return &Dao{}
}
func (d *Dao) Do() {
fmt.Println("do dao")
}service/service.go
package service
import (
"fmt"
"wirelearn/dao"
)
// 實現(xiàn)接口的結(jié)構(gòu)體
type Service struct {
dao *dao.Dao
}
func NewService(dao *dao.Dao) *Service {
return &Service{
dao: dao,
}
}
func (s *Service) Execute() {
fmt.Println("Executing service...")
s.dao.Do()
}wiretest/wire.go
//go:build wireinject
// +build wireinject
package wiretest
import (
"github.com/google/wire"
"wire-learn/wirelearn/dao"
"wire-learn/wirelearn/controller"
"wire-learn/wirelearn/service"
)
var providerSet = wire.NewSet(
controller.NewController,
service.NewService,
dao.NewDao,
)
func Initialize() (*controller.Controller, error) {
panic(wire.Build(providerSet))
}在wire.go文件中,我們只需要把生成實例的方法指針放到wire.NewSet中,就完成主要作用wire的編寫,Initialize方法的返回就是我們要給的最終實例main.go
func main() {
controller, err := wiretest.Initialize()
if err != nil {
panic(err)
}
controller.Run()
}在main中,我們只需要調(diào)用wiretest.Initialize中的方法獲取對應(yīng)的實例。這塊就是wire自動生成的代碼,通常和wire.go在同一個文件夾中
看下我們生成的wire_gen.go的代碼吧
// Code generated by Wire. DO NOT EDIT.
//go:generate go run -mod=mod github.com/google/wire/cmd/wire
//go:build !wireinject
// +build !wireinject
package wiretest
import (
"github.com/google/wire"
"wirelearn/controller"
"wirelearn/dao"
"wirelearn/service"
)
// Injectors from wire.go:
func Initialize() (*controller.Controller, error) {
daoDao := dao.NewDao()
serviceService := service.NewService(daoDao)
controllerController := controller.NewController(serviceService)
return controllerController, nil
}
// wire.go:
var providerSet = wire.NewSet(controller.NewController, service.NewService, dao.NewDao)可以看到Initialize方法中的代碼和我們沒使用wire之前,在main方法中寫的,基本相同。所以我們也可以大致了解wire在實際任務(wù)中實際工作方式。
總結(jié)
本文通過示例講解了依賴注入的原理及其在 Go 語言中的實際應(yīng)用,尤其是利用 Wire 工具自動生成依賴代碼的過程。通過依賴注入,代碼更加模塊化、可測試,并減少了各模塊之間的耦合,增強(qiáng)了可維護(hù)性。 Wire 工具進(jìn)一步簡化了這個過程,避免了繁瑣的手動編寫依賴初始化代碼。
到此這篇關(guān)于Go 依賴注入庫wire基本使用的文章就介紹到這了,更多相關(guān)Go 依賴注入庫wire內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Golang根據(jù)job數(shù)量動態(tài)控制每秒?yún)f(xié)程的最大創(chuàng)建數(shù)量方法詳解
這篇文章主要介紹了Golang根據(jù)job數(shù)量動態(tài)控制每秒?yún)f(xié)程的最大創(chuàng)建數(shù)量方法2024-01-01
CSP communicating sequential processes并發(fā)模型
這篇文章主要為大家介紹了CSP communicating sequential processes并發(fā)模型,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-05-05
golang基于websocket實現(xiàn)的簡易聊天室程序
這篇文章主要介紹了golang基于websocket實現(xiàn)的簡易聊天室,分析了websocket的下載、安裝及使用實現(xiàn)聊天室功能的相關(guān)技巧,需要的朋友可以參考下2016-07-07

