gin 集成 Wire

好的,下面是一个完整的 Go Web 项目启动模板,基于:

  • Gin:作为 Web 框架
  • Google Wire:用于依赖注入
  • GORM:作为数据库 ORM
  • Viper:配置管理(可选)
  • 项目结构清晰,适合中大型项目进行扩展与维护

✅ 项目结构一览

your_project/
├── cmd/
│   └── server/               # 程序启动入口
│       └── main.go
├── internal/
│   ├── handler/              # 控制器
│   ├── repository/           # 数据访问层
│   ├── service/              # 业务逻辑层
│   └── wire/                 # Wire 依赖注入
│       ├── injector.go       # Wire 注入入口
│       └── wire.go           # Wire provider 定义
├── pkg/
│   ├── config/               # 配置读取
│   └── logger/               # 日志封装
├── go.mod
├── go.sum
└── wire_gen.go               # 自动生成文件

🧱 代码示例分模块展开


1. cmd/server/main.go

package main

import (
    "log"
    "your_project/internal/wire"
)

func main() {
    server, err := wire.InitServer()
    if err != nil {
        log.Fatalf("failed to start server: %v", err)
    }
    if err := server.Run(":8080"); err != nil {
        log.Fatal(err)
    }
}

2. internal/wire/wire.go

//go:build wireinject
// +build wireinject

package wire

import (
    "github.com/google/wire"
    "github.com/gin-gonic/gin"
    "your_project/internal/handler"
    "your_project/internal/repository"
    "your_project/internal/service"
    "your_project/pkg/config"
    "your_project/pkg/logger"
    "gorm.io/gorm"
)

func InitServer() (*gin.Engine, error) {
    wire.Build(
        config.InitConfig,
        logger.InitLogger,
        config.InitDB,
        repository.NewUserRepository,
        service.NewUserService,
        handler.NewRouter,
    )
    return &gin.Engine{}, nil
}

3. internal/wire/injector.go(Wire 生成文件)

// wire_gen.go 会自动生成,不手写

运行:

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

4. pkg/config/config.go

package config

import (
    "fmt"
    "github.com/spf13/viper"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

var Cfg *viper.Viper

func InitConfig() (*viper.Viper, error) {
    v := viper.New()
    v.SetConfigName("app")
    v.AddConfigPath("./config")
    v.SetConfigType("yaml")

    if err := v.ReadInConfig(); err != nil {
        return nil, fmt.Errorf("read config failed: %w", err)
    }
    Cfg = v
    return v, nil
}

func InitDB(v *viper.Viper) (*gorm.DB, error) {
    dsn := v.GetString("mysql.dsn")
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
    return db, err
}

5. pkg/logger/logger.go

package logger

import (
    "go.uber.org/zap"
)

var Logger *zap.Logger

func InitLogger() (*zap.Logger, error) {
    var err error
    Logger, err = zap.NewDevelopment()
    if err != nil {
        return nil, err
    }
    return Logger, nil
}

6. internal/repository/user_repository.go

package repository

import (
    "context"
    "gorm.io/gorm"
)

type UserRepository struct {
    db *gorm.DB
}

func NewUserRepository(db *gorm.DB) *UserRepository {
    return &UserRepository{db: db}
}

func (r *UserRepository) Ping(ctx context.Context) error {
    sqlDB, err := r.db.DB()
    if err != nil {
        return err
    }
    return sqlDB.PingContext(ctx)
}

7. internal/service/user_service.go

package service

import (
    "context"
    "your_project/internal/repository"
)

type UserService struct {
    repo *repository.UserRepository
}

func NewUserService(repo *repository.UserRepository) *UserService {
    return &UserService{repo: repo}
}

func (s *UserService) HealthCheck(ctx context.Context) bool {
    return s.repo.Ping(ctx) == nil
}

8. internal/handler/router.go

package handler

import (
    "github.com/gin-gonic/gin"
    "your_project/internal/service"
)

func NewRouter(svc *service.UserService) *gin.Engine {
    r := gin.Default()

    r.GET("/ping", func(c *gin.Context) {
        if svc.HealthCheck(c.Request.Context()) {
            c.JSON(200, gin.H{"msg": "ok"})
        } else {
            c.JSON(500, gin.H{"msg": "db down"})
        }
    })

    return r
}

9. config/app.yaml

mysql:
  dsn: root:password@tcp(127.0.0.1:3306)/your_db?charset=utf8mb4&parseTime=True

✅ 最终运行方式

  1. 配置好数据库连接和配置文件
  2. 运行 Wire 生成依赖注入代码:
wire
  1. 启动服务:
go run cmd/server/main.go

本文为原创内容,作者:闲鹤,原文链接:https://blog.uwenya.cc/1601.html,转载请注明出处。

发表评论