Go 依赖注入之 wire 库

PS: 若不了解控制反转和依赖注入,可参考博文:https://blog.csdn.net/qq_38269333/article/details/139300610?spm=1001.2014.3001.5501

简介

wire 库是管理和解析依赖关系的。

随着项目规模的增长,手动管理依赖关系变得越来越困难,容易导致代码的复杂性和耦合度增加。为了解决这一问题,Google 开发了一个名为 wire 的依赖注入工具,它可以自动生成依赖注入代码,帮助开发者管理依赖关系,提高代码的清晰度和可维护性。

GitHub 地址:https://github.com/google/wire

安装命令

go get github.com/google/wire/cmd/wire

使用示例

以常见的 controller、service、model 模式为例,示例如下:

代码片段

user.go

package main

import (
    "database/sql"
    "net/http"
)

// User 是用户模型
type User struct {
    ID    int
    Name  string
    Email string
}

// UserRepository 是用户存储库
type UserRepository struct {
    DB *Database
}

// UserService 是用户服务
type UserService struct {
    Repo *UserRepository
}

// UserController 是用户控制器
type UserController struct {
    Service *UserService
}

// GetUserByID 处理获取用户的HTTP请求
func (controller *UserController) GetUserByID(w http.ResponseWriter, r *http.Request) {
    id := 1 // 假设我们从请求中获取了用户ID
    user, err := controller.Service.GetUserByID(id)
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }
    // 返回用户信息
}

// NewUserRepository 创建一个新的用户存储库
func NewUserRepository(db *Database) *UserRepository {
    return &UserRepository{DB: db}
}

// NewUserService 创建一个新的用户服务
func NewUserService(repo *UserRepository) *UserService {
    return &UserService{Repo: repo}
}

// NewUserController 创建一个新的用户控制器
func NewUserController(service *UserService) *UserController {
    return &UserController{Service: service}
}

wire.go

//+build wireinject

package main

import (
    "github.com/google/wire"
)

// InitializeUserController 初始化用户控制器
func InitializeUserController() (*UserController, error) {
    wire.Build(NewUserController, NewUserService, NewUserRepository, NewDatabase)
    return nil, nil
}

main.go

package main

import (
    "log"
    "net/http"
)

func main() {
    controller, err := InitializeUserController()
    if err != nil {
        log.Fatalf("failed to initialize user controller: %v", err)
    }

    http.HandleFunc("/user", controller.GetUserByID)
    log.Println("Starting server on :8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatalf("failed to start server: %v", err)
    }
}

执行 wire 命令即可在当前文件夹下生成 wire_gen.go 文件,内部实现了 InitializeUserController 方法, 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 main

import (
	_ "github.com/go-sql-driver/mysql"
)

// Injectors from wire.go:

// InitializeUserController 初始化用户控制器
func InitializeUserController() (*UserController, error) {
	database, err := NewDatabase()
	if err != nil {
		return nil, err
	}
	userRepository := NewUserRepository(database)
	userService := NewUserService(userRepository)
	userController := NewUserController(userService)
	return userController, nil
}