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/wire2. 声明模块依赖关系
在用户模块创建 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/userWire 会生成 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 的价值不在于炫技,而是把模块依赖固定成清晰的生成代码:谁依赖谁、从哪里构造,一眼能看懂,运行时也没有额外反射开销。
