Skip to content

Gin 实战 8:用 Wire 组装模块依赖

用户模块现在需要手写 Repository -> Service -> Handler。模块少时还好,模块多了之后初始化代码会越来越散。本章引入 Wire,把“怎么 new 出一个 Handler”交给代码生成,让路由层只关心最终能用的 Handler。

1. 安装 Wire

bash
go install github.com/google/wire/cmd/wire@latest
go get github.com/google/wire

2. 声明模块依赖关系

在用户模块创建 internal/system/user/wire.go

go
//go:build wireinject

package user

import (
    "github.com/google/wire"
    "youlai-gin/internal/system/user/handler"
    "youlai-gin/internal/system/user/repository"
    "youlai-gin/internal/system/user/service"
)

// InitHandler 声明用户模块 Handler 的构造规则。
// 这个函数不会在运行时执行,Wire 会根据它生成 wire_gen.go。
func InitHandler() *handler.Handler {
    wire.Build(
        // 构造顺序由参数类型自动推导:
        // NewRepository() -> NewService(repo) -> NewHandler(service)
        repository.NewRepository,
        service.NewService,
        handler.NewHandler,
    )

    // wireinject 文件只用于生成代码,这里的 return nil 是固定写法。
    return nil
}

执行:

bash
wire ./internal/system/user

Wire 会生成 wire_gen.go,里面是普通 Go 代码:

go
func InitHandler() *handler.Handler {
    // 这就是 Wire 生成的普通 Go 代码。
    // 没有反射,也没有运行时容器。
    repo := repository.NewRepository()
    svc := service.NewService(repo)
    h := handler.NewHandler(svc)
    return h
}

3. 路由中使用

go
func RegisterRoutes(r *gin.RouterGroup) {
    // 路由层只拿最终 Handler,不再关心中间依赖如何组装。
    h := InitHandler()

    users := r.Group("/users")
    users.GET("", h.Page)
    users.POST("", h.Create)
}

Wire 的价值不在于炫技,而是把模块依赖固定成清晰的生成代码:谁依赖谁、从哪里构造,一眼能看懂,运行时也没有额外反射开销。

基于 MIT 许可发布 · 如需部署协助或二开定制,请查看 支持与合作