1. wire 简介
wire 是一个 Golang 的依赖注入框架(类比 Spring 框架提供的依赖注入功能)
这里关乎到编程世界当中一条好用的设计原则:A用到了B,那么B一定是通过依赖注入的方式提供给A的
举一个例子:现在有一个 CodeService(验证码服务)需要调用到 SmsService(短信服务)来完成发送验证码的功能,此时在 CodeService 内部是不知道也不应该了解如何初始化 SmsService 的,那么就要求由外部传入已经构造好的 SmsService 实例
依赖注入有以下优点:
- 依赖方与被依赖方耦合度较低
- 可以复用公共组件(比如 MySQL、Redis 等数据库连接对象)
- 测试方便
- 扩展性良好
2. wire 安装与下载
下载 wire 对应源码包:go install github.com/google/wire/cmd/wire@latest

💡 温馨提示:install 命令会自动将 wire 下载到 GOPATH 下的 bin 目录,只有配置该路径环境变量才能使用 wire 命令
3. 项目基本结构
该实例项目参考 DDD 架构规范:

- repository:领域对象的存储
- dao:存储到关系型数据库
- service:领域对象的行为(业务相关)
- web:与 HTTP 请求交互
- db.go:初始化数据库连接
- wire.go:依赖注入代码实现
- main.go:项目启动入口
- wire_gen.go:依赖注入生成的文件
repository/dao/user.go
go
package dao
import "gorm.io/gorm"
type UserDAO struct {
db *gorm.DB
}
func NewUserDAO(db *gorm.DB) *UserDAO {
return &UserDAO{
db: db,
}
}
repository/user.go
go
package repository
import "wire_demo/repository/dao"
type UserRepository struct {
userDAO *dao.UserDAO
}
func NewUserRepository(userDAO *dao.UserDAO) *UserRepository {
return &UserRepository{
userDAO: userDAO,
}
}
service/user.go
go
package service
import "wire_demo/repository"
type UserService struct {
repo *repository.UserRepository
}
func NewUserService(repo *repository.UserRepository) *UserService {
return &UserService{
repo: repo,
}
}
web/user.go
go
package web
import (
"github.com/gin-gonic/gin"
"net/http"
"wire_demo/service"
)
type UserHandler struct {
userSvc *service.UserService
}
func NewUserHandler(userSvc *service.UserService) *UserHandler {
return &UserHandler{
userSvc: userSvc,
}
}
func (u *UserHandler) SayHello(ctx *gin.Context) {
ctx.String(http.StatusOK, "Hello,World!")
return
}
func (u *UserHandler) RegisterRoutes(server *gin.Engine) {
server.GET("/hello", u.SayHello)
}
db.go
go
package main
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func InitDB() *gorm.DB {
db, err := gorm.Open(mysql.Open("root:QWEzxc123456@tcp(localhost:3306)/webook"))
if err != nil {
panic(err)
}
return db
}
3. wire 快速入门
步骤一 :在项目根目录下创建wire.go
go
//go:build wireinject
package main
import (
"github.com/google/wire"
"wire_demo/repository"
"wire_demo/repository/dao"
"wire_demo/service"
"wire_demo/web"
)
func Init() *web.UserHandler {
wire.Build(
InitDB,
dao.NewUserDAO,
repository.NewUserRepository,
service.NewUserService,
web.NewUserHandler,
)
return new(web.UserHandler)
}
💡 温馨提示:
- 在文件上方使用固定格式 //go:build wireinject 表明这是依赖注入的编译模板文件
- 创建一个函数内部使用 wire.Build 方法,传入各种构造方法,wire 会自动分析依赖关系
- 返回值无所谓(wire 内部会帮你进行替换)
步骤二 :在 wire.go 同级目录下命令行执行wire
命令

此时也会发现项目同级目录出现一个wire_gen.go
文件,这就是编译生成的文件(内部已经帮你写好了各种构造方法以及依赖之间的传递)
步骤三:在 main.go 文件中正常使用即可!
go
package main
import "github.com/gin-gonic/gin"
func main() {
server := gin.Default()
userHandler := Init()
userHandler.RegisterRoutes(server)
server.Run(":8080")
}