go wire 入門
一、介紹
wire 是提供 go 的依賴注入
官方包地址爲 https://github.com/google/wire 我們打開官方 url,安裝方式如下
go install github.com/google/wire/cmd/wire
安裝後,就有 wire 命令可以用了,我試試在命令行工具裏,輸入 wire
➜ wire
輸出:
wire: -: no Go files /Users/zhanghaisheng/study/dataStructure/wirewire: generate failed
wire: generate failed
我們查看 wire 命令支持哪些參數,在命令行工具裏,輸入 wire help
➜ wire help
輸出:
Usage: wire <flags> <subcommand> <subcommand args>
Subcommands:
check print any Wire errors found
commands list all command names
diff output a diff between existing wire_gen.go files and what gen would generate
flags describe all known top-level flags
gen generate the wire_gen.go file for each package
help describe subcommands and their syntax
show describe all top-level provider sets
Use "wire flags" for a list of top-level flags
可以看到 wire 支持的命令
二、入門案例:controller,service,model 爲例子。
在一個 web 服務,我們會把路由映射到 controller 的方法上,這裏簡單建立一個 controller。我們在一個學習的目錄下建立下面 4 個空文件
.
├── user_controller.go //controller文件
├── user_model.go //model 以及數據庫操作文件
├── user_service.go //user相關的邏輯
└── user_test.go //test測試用例文件
user_model.go 文件爲數據結構 model,我們打開寫入以下內容:
type UserModel struct {
Name string
Age int
}
func NewUserModel() UserModel {
return UserModel{Name: "hi", Age: 10}
}
user_service.go 文件爲 user 服務類,我們在裏面寫一些操作 user 的邏輯。打開文件,寫入以下內容:
type UserService struct {
userModel UserModel
}
func NewUserService(user UserModel) UserService {
return UserService{
userModel: user,
}
}
func (s UserService) GetName() string {
return s.userModel.Name
}
UserService 結構體裏面,有屬性字段 userModel,這個在我們 NewUserService() 的時候,以參數傳進來。
user_controller.go 文件爲 controller 類,我們在這裏處理一些用戶參數,以及調度不同的 service,打開寫入以下內容:
type UserController struct {
userService UserService
}
func NewUserController(userService UserService) UserController {
return UserController{
userService: userService,
}
}
func (c UserController) GetName() string {
return c.userService.GetName()
}
三、傳統的初始化對象方式
3.1、 初始化 UserModel
我們在 user_test.go 裏輸入如下代碼:
func TestModel(t *testing.T) {
md := NewUserModel()
t.Log(md)
}
我們使用的時候,NewUserModel(),沒有傳參,是最簡單的 new
3.2、 初始化 UserService
我們在 user_test.go 裏輸入如下代碼:
func TestService(t *testing.T) {
service := NewUserService(NewUserModel())
t.Log(service.GetName())
}
我們使用 NewUserService(NewUserModel()) 初始化 UserService 對象。
3.3、 初始化 UserController
我們在 user_test.go 裏輸入如下代碼:
func TestController(t *testing.T) {
c := NewUserController(NewUserService(NewUserModel()))
t.Log(c.GetName())
}
我們使用 NewUserController(NewUserService(NewUserModel())) 初始化 UserController 對象。
3.4 這種方式有什麼問題?
這幾種方式我們都是以對象注入的方式,初始化對象,對於一個 controler,目前只有一個屬性字段 userService,如果有 4,5 個會怎麼樣,那麼這個初始化就會變的非常長!比如下面這樣
NewUserController(NewUserService(NewUserModel()),NewRedisService(NewUserModel()),NewCacheService(NewUserModel()))
有沒有更好的方案?有,依賴注入,wire 庫。
四、使用 wire 依賴注入
我們新建一個同級目錄 wireinject 如下
.
├── user_controller.go
├── user_model.go
├── user_service.go
├── user_test.go
└── wireinject
然後執行
➜ cd wireinject
在 wireinject 下面,新建一個 wire.go 文件,初始代碼如下:
//go:build wireinject
// +build wireinject
package wireinject
4.1 初始化 UserModel
我們在 wire.go 輸入
func NewUserModel() demo.UserModel {
panic(
wire.Build(
demo.NewUserModel,
))
}
然後執行
➜ wire
會發現 wireinject 目錄下,多了一個文件 wire_gen.go
.
├── wire.go
└── wire_gen.go
這個爲 wire 命令生成
4.2、 初始化 UserService
我們在 wire.go 裏輸入如下代碼:
func NewUserService() demo.UserService {
panic(
wire.Build(
demo.NewUserModel,
demo.NewUserService,
))
}
我們使用 NewUserService() 初始化 UserService 對象。return 返回值爲 demo.UserService 對象,在函數里用 panic 包裹 wire.build(....), 其中 wire.build 爲我們要依賴注入的函數,把注入到這個函數里,然後自動的生成對象,這裏參數是 demo.NewUserModel,demo.NewUserService, 爲裏面需要初始化的對象。
然後執行
➜ wire
4.3、 初始化 UserController
我們在 wire.go 裏輸入如下代碼:
func NewUserController() demo.UserController {
panic(
wire.Build(
demo.NewUserModel,
demo.NewUserService,
demo.NewUserController,
))
}
然後執行
➜ wire
4.4 使用
我們在 wireinject 目錄下新建 wire_test.go 並輸入代碼:
package wireinject
import "testing"
func TestModel(t *testing.T) {
md := NewUserModel()
t.Log(md)
}
func TestService(t *testing.T) {
service := NewUserService()
t.Log(service.GetName())
}
func TestController(t *testing.T) {
c := NewUserController()
t.Log(c.GetName())
}
此時發現我們並不需要輸入參數了!這就是 wire 代碼的依賴注入,它自動幫我們注入參數!
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/0S98jBCMHGqbMShP8Gf5gQ