wire 依赖注入架构
在 Go 中使用 Gin、Gorm、Wire 来进行依赖注入和三层架构设计是常见的做法。这里,我会展示如何使用三层架构(Controller、Service、Repository)来组织代码,并通过 Wire 实现依赖注入。这样做可以使代码更加模块化,便于扩展和维护。
三层架构简介
- Controller:接收请求并响应,它负责请求和响应的处理,调用 Service 层来执行业务逻辑。
- Service:处理具体的业务逻辑,通常是调用 Repository 层来访问数据。
- Repository:与数据库交互,封装了 Gorm 的 CRUD 操作。
示例结构
/app
├── controller
│ └── user_controller.go
├── service
│ └── user_service.go
└── repository
└── user_repository.go
/wire.go
/main.go1. 创建 Gorm 模型
首先,我们定义一个 User 模型,用 Gorm 来进行数据存取。
go
// /app/repository/user_repository.go
package repository
import (
"gorm.io/gorm"
)
// User 模型
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:255"`
Age uint
}
// UserRepository 提供与数据库交互的操作
type UserRepository struct {
DB *gorm.DB
}
// NewUserRepository 创建 UserRepository
func NewUserRepository(db *gorm.DB) *UserRepository {
return &UserRepository{DB: db}
}
// GetUserByID 获取用户
func (r *UserRepository) GetUserByID(id uint) (*User, error) {
var user User
if err := r.DB.First(&user, id).Error; err != nil {
return nil, err
}
return &user, nil
}
// CreateUser 创建用户
func (r *UserRepository) CreateUser(user *User) error {
return r.DB.Create(user).Error
}2. 创建 Service 层
UserService 层负责具体的业务逻辑,它会调用 UserRepository 进行数据库操作。
go
// /app/service/user_service.go
package service
import (
"gin-wire-example/app/repository"
)
// UserService 提供与业务逻辑相关的操作
type UserService struct {
Repo *repository.UserRepository
}
// NewUserService 创建 UserService
func NewUserService(repo *repository.UserRepository) *UserService {
return &UserService{Repo: repo}
}
// GetUserByID 获取用户信息
func (s *UserService) GetUserByID(id uint) (*repository.User, error) {
return s.Repo.GetUserByID(id)
}
// CreateUser 创建用户
func (s *UserService) CreateUser(user *repository.User) error {
return s.Repo.CreateUser(user)
}3. 创建 Controller 层
UserController 层负责 HTTP 请求的接收和响应,并调用 UserService 来处理业务。
go
// /app/controller/user_controller.go
package controller
import (
"github.com/gin-gonic/gin"
"gin-wire-example/app/service"
"net/http"
"strconv"
)
// UserController 提供与 HTTP 请求相关的操作
type UserController struct {
Service *service.UserService
}
// NewUserController 创建 UserController
func NewUserController(service *service.UserService) *UserController {
return &UserController{Service: service}
}
// GetUser 获取用户信息
func (c *UserController) GetUser(ctx *gin.Context) {
id, err := strconv.Atoi(ctx.Param("id"))
if err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid user ID"})
return
}
user, err := c.Service.GetUserByID(uint(id))
if err != nil {
ctx.JSON(http.StatusNotFound, gin.H{"error": "User not found"})
return
}
ctx.JSON(http.StatusOK, user)
}
// CreateUser 创建用户
func (c *UserController) CreateUser(ctx *gin.Context) {
var user service.User
if err := ctx.ShouldBindJSON(&user); err != nil {
ctx.JSON(http.StatusBadRequest, gin.H{"error": "Invalid data"})
return
}
if err := c.Service.CreateUser(&user); err != nil {
ctx.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to create user"})
return
}
ctx.JSON(http.StatusCreated, user)
}4. 使用 Wire 进行依赖注入
在 wire.go 中定义依赖关系,并利用 Wire 自动生成代码来注入依赖。
go
// /wire.go
//+build wireinject
package main
import (
"gin-wire-example/app/controller"
"gin-wire-example/app/repository"
"gin-wire-example/app/service"
"github.com/google/wire"
"gorm.io/gorm"
)
// Set 提供依赖集合
var Set = wire.NewSet(
NewDB, // 创建数据库连接
repository.NewUserRepository, // 创建 UserRepository
service.NewUserService, // 创建 UserService
controller.NewUserController, // 创建 UserController
)
// InitializeApp 初始化应用
func InitializeApp() (*controller.UserController, error) {
wire.Build(Set)
return nil, nil
}
// NewDB 创建 Gorm 数据库连接
func NewDB() (*gorm.DB, error) {
// 这里假设已经配置了数据库连接
// db, err := gorm.Open(...)
return &gorm.DB{}, nil // 实际上应返回连接的数据库实例
}5. 主程序启动
在 main.go 中,使用 Wire 初始化应用并启动 Gin 服务。
go
// /main.go
package main
import (
"fmt"
"github.com/gin-gonic/gin"
"log"
)
func main() {
// 初始化控制器
controller, err := InitializeApp()
if err != nil {
log.Fatal(err)
}
// 创建 Gin 路由
router := gin.Default()
// 路由配置
router.GET("/users/:id", controller.GetUser)
router.POST("/users", controller.CreateUser)
// 启动 Gin
if err := router.Run(":8080"); err != nil {
log.Fatal("Error starting server:", err)
}
}6. 运行 wire 命令生成代码
在项目根目录运行以下命令来生成 wire_gen.go 文件:
bash
wirewire_gen.go 文件将自动生成,完成所有依赖的注入和初始化。
总结
- 三层架构:我们将代码分为 Controller、Service 和 Repository 层。Controller 层处理 HTTP 请求,Service 层处理业务逻辑,Repository 层与数据库交互。
- 依赖注入:通过
Wire,我们自动注入每一层的依赖,避免了手动管理依赖关系。 - 数据库操作:通过
Gorm在 Repository 层进行数据库操作。Wire负责创建和注入数据库连接。
通过这种方式,我们将 Go + Gin + Gorm + Wire 的组合用于开发应用程序,确保了代码的模块化、可维护性和清晰的依赖关系管理。