17 changed files with 0 additions and 842 deletions
@ -1,68 +0,0 @@ |
|||
# Aurora Golang Clean Architecture Template |
|||
|
|||
这是一个基于 **Go + Gin + GORM** 的多数据库自动切换项目模板,遵循 Clean Architecture 分层思想。模板默认支持 SQLite、MySQL 与 PostgreSQL,使用配置文件即可切换数据库驱动。 |
|||
|
|||
## 结构说明 |
|||
|
|||
``` |
|||
. |
|||
├── cmd/ |
|||
│ └── server/ # 应用入口 |
|||
├── configs/ |
|||
│ └── config.yaml # 默认配置文件 |
|||
├── internal/ |
|||
│ ├── config/ # 配置加载 |
|||
│ ├── domain/ # 领域模型和接口 |
|||
│ ├── infrastructure/ # 数据库与仓储实现 |
|||
│ ├── interface/ # HTTP 适配器 |
|||
│ └── usecase/ # 应用服务 |
|||
├── pkg/ |
|||
│ └── logger/ # 日志封装 |
|||
└── go.mod |
|||
``` |
|||
|
|||
## 快速开始 |
|||
|
|||
1. 安装依赖 |
|||
```bash |
|||
go mod tidy |
|||
``` |
|||
|
|||
2. 根据需要调整 `configs/config.yaml` 或 `.env` 中的数据库驱动参数,可选值: |
|||
- `sqlite` |
|||
- `mysql` |
|||
- `postgres` / `postgresql` |
|||
|
|||
3. 运行服务 |
|||
```bash |
|||
go run ./cmd/server |
|||
``` |
|||
|
|||
4. 示例接口 |
|||
- `GET /api/v1/users` |
|||
- `GET /api/v1/users/:id` |
|||
- `POST /api/v1/users` |
|||
|
|||
## 数据库自动切换 |
|||
|
|||
通过配置文件中的 `database.driver` 自动选择对应的 GORM 驱动: |
|||
|
|||
- SQLite 会在 `data/aurora.db` 下生成数据库文件(路径可配置) |
|||
- MySQL、PostgreSQL 根据配置生成 DSN,支持额外连接参数 |
|||
|
|||
## 清晰的分层设计 |
|||
|
|||
- `domain`: 定义核心业务实体与仓储接口 |
|||
- `usecase`: 聚合业务逻辑,依赖仓储接口 |
|||
- `infrastructure`: 提供 GORM 仓储实现、数据库初始化等 |
|||
- `interface/http`: 提供 Gin HTTP 适配器 |
|||
- `cmd/server`: 组装依赖、启动服务 |
|||
|
|||
## 下一步 |
|||
|
|||
- 扩展更多领域模型与用例 |
|||
- 集成依赖注入框架 |
|||
- 增加测试与 CI/CD |
|||
|
|||
欢迎在此模板基础上继续拓展,构建您的业务服务。 |
|||
|
|||
@ -1,58 +0,0 @@ |
|||
package main |
|||
|
|||
import ( |
|||
"fmt" |
|||
"log" |
|||
"path/filepath" |
|||
|
|||
"auroragolang/docs" |
|||
"auroragolang/internal/config" |
|||
"auroragolang/internal/domain/model" |
|||
"auroragolang/internal/infrastructure/database" |
|||
infraRepo "auroragolang/internal/infrastructure/repository" |
|||
httpInterface "auroragolang/internal/interface/http" |
|||
"auroragolang/internal/usecase" |
|||
"auroragolang/pkg/logger" |
|||
|
|||
"gorm.io/gorm" |
|||
) |
|||
|
|||
// @title Aurora Service API
|
|||
// @version 1.0
|
|||
// @description Aurora Golang 示例 REST API,基于 Gin + GORM。
|
|||
// @BasePath /api/v1
|
|||
func main() { |
|||
root := "." |
|||
cfg, err := config.LoadConfig(filepath.Join(root, "configs")) |
|||
if err != nil { |
|||
log.Fatalf("加载配置失败: %v", err) |
|||
} |
|||
|
|||
appLogger := logger.New(cfg.App.Name) |
|||
|
|||
docs.SwaggerInfo.Version = cfg.App.Env |
|||
docs.SwaggerInfo.BasePath = "/api/v1" |
|||
|
|||
db, err := database.Connect(cfg.Database) |
|||
if err != nil { |
|||
appLogger.Fatalf("数据库连接失败: %v", err) |
|||
} |
|||
|
|||
autoMigrate(db, appLogger) |
|||
|
|||
userRepo := infraRepo.NewGormUserRepository(db) |
|||
userService := usecase.NewUserService(userRepo) |
|||
router := httpInterface.NewRouter(userService) |
|||
|
|||
appLogger.Printf("服务启动: 端口 %d,环境 %s", cfg.App.Port, cfg.App.Env) |
|||
if err := router.Run(fmt.Sprintf(":%d", cfg.App.Port)); err != nil { |
|||
appLogger.Fatalf("服务器启动失败: %v", err) |
|||
} |
|||
} |
|||
|
|||
func autoMigrate(db *gorm.DB, log *logger.Logger) { |
|||
if err := db.AutoMigrate(&model.User{}); err != nil { |
|||
log.Fatalf("自动迁移失败: %v", err) |
|||
} |
|||
} |
|||
|
|||
@ -1,24 +0,0 @@ |
|||
app: |
|||
name: AuroraService |
|||
env: development |
|||
port: 8080 |
|||
|
|||
database: |
|||
driver: sqlite |
|||
sqlite: |
|||
path: data/aurora.db |
|||
mysql: |
|||
host: localhost |
|||
port: 3306 |
|||
user: root |
|||
password: password |
|||
dbname: aurora |
|||
params: charset=utf8mb4&parseTime=True&loc=Local |
|||
postgres: |
|||
host: localhost |
|||
port: 5432 |
|||
user: postgres |
|||
password: password |
|||
dbname: aurora |
|||
sslmode: disable |
|||
|
|||
@ -1,40 +0,0 @@ |
|||
## 项目架构说明 |
|||
|
|||
### 技术栈概览 |
|||
- Web 框架:Gin (`internal/interface/http`) |
|||
- ORM 层:GORM(`internal/infrastructure/database`、`internal/infrastructure/repository`) |
|||
- 接口文档:Swaggo(`docs/docs.go`、`/swagger` 路由) |
|||
- 配置管理:Viper + YAML (`internal/config`) |
|||
- 日志:自定义包装(`pkg/logger`) |
|||
|
|||
### 数据库自动切换 |
|||
- 配置文件 `configs/config.yaml` 通过 `database.driver` 控制当前使用的数据库(未设置时自动回退为 `sqlite`)。 |
|||
- 支持的驱动: |
|||
- `sqlite`:默认用于本地与轻量测试;路径可通过 `database.sqlite.path` 自定义。 |
|||
- `mysql`:提供账号、主机、端口、库名与参数配置。 |
|||
- `postgres`:提供账号、主机、端口、库名与 SSL 模式配置。 |
|||
- `internal/infrastructure/database/database.go` 根据配置动态选择驱动并建立连接,确保应用无需改动即可切换数据库。 |
|||
|
|||
### 自动迁移机制 |
|||
- `cmd/server/main.go` 中的 `autoMigrate` 函数会在启动时对 `internal/domain/model` 内的模型执行 `db.AutoMigrate`。 |
|||
- 当前示例模型为 `model.User`,可按需扩展更多模型。 |
|||
|
|||
### 分层结构(类 Clean Architecture) |
|||
- `internal/domain`:领域模型与仓储接口。 |
|||
- `internal/usecase`:业务用例与应用服务。 |
|||
- `internal/infrastructure`:具体实现(数据库、仓储等)。 |
|||
- `internal/interface/http`:Gin 路由与控制器。 |
|||
- `cmd/server`:程序入口,负责初始化配置、日志、数据库、依赖注入以及启动 HTTP 服务。 |
|||
|
|||
### 配置流程 |
|||
1. `cmd/server/main.go` 调用 `config.LoadConfig` 读取 `configs` 目录下的 `config.yaml`。 |
|||
2. 根据配置创建日志实例,初始化数据库连接。 |
|||
3. 执行自动迁移,注入仓储与服务,再初始化 Gin 路由并启动服务。 |
|||
4. 注册 `/swagger/*any` 路由,直接访问并查看自动生成的 Swagger UI。 |
|||
|
|||
### 快速验证 |
|||
1. 修改 `configs/config.yaml` 中的 `database.driver` 为 `sqlite`、`mysql` 或 `postgres`。 |
|||
2. 启动服务 `go run ./cmd/server`,确认可正常连接并迁移数据库。 |
|||
3. 访问 `GET /api/v1/users` 等 REST 接口验证路由与仓储是否正常工作。 |
|||
|
|||
|
|||
@ -1,41 +0,0 @@ |
|||
## 项目代码目录 |
|||
|
|||
``` |
|||
AuroraGolang/ |
|||
├── cmd/ |
|||
│ └── server/ |
|||
│ └── main.go # 应用入口,加载配置、初始化依赖、启动 Gin |
|||
├── configs/ |
|||
│ └── config.yaml # 默认配置(App、数据库驱动与连接信息) |
|||
├── internal/ |
|||
│ ├── config/ |
|||
│ │ └── config.go # 配置加载与环境覆盖 |
|||
│ ├── domain/ |
|||
│ │ ├── model/ |
|||
│ │ │ └── user.go # 领域模型定义 |
|||
│ │ └── repository/ |
|||
│ │ └── user_repository.go# 仓储接口(领域层) |
|||
│ ├── infrastructure/ |
|||
│ │ ├── database/ |
|||
│ │ │ └── database.go # 数据库连接与驱动切换逻辑 |
|||
│ │ └── repository/ |
|||
│ │ └── user_repository_gorm.go |
|||
│ ├── interface/ |
|||
│ │ └── http/ |
|||
│ │ ├── router.go # Gin 路由注册 |
|||
│ │ └── user_handler.go # 控制器实现 |
|||
│ └── usecase/ |
|||
│ └── user_service.go # 应用服务/用例 |
|||
├── pkg/ |
|||
│ └── logger/ |
|||
│ └── logger.go # 日志封装 |
|||
├── docs/ |
|||
│ ├── architecture.md # 架构说明 |
|||
│ ├── code_structure.md # 代码目录概览 |
|||
│ └── docs.go # Swaggo 生成的 Swagger 模板(手动维护) |
|||
├── go.mod |
|||
├── README.md |
|||
└── modify.md |
|||
``` |
|||
|
|||
|
|||
@ -1,227 +0,0 @@ |
|||
package docs |
|||
|
|||
import ( |
|||
"encoding/json" |
|||
"strings" |
|||
|
|||
"github.com/swaggo/swag" |
|||
) |
|||
|
|||
const docTemplate = `{ |
|||
"swagger": "2.0", |
|||
"info": { |
|||
"description": "{{.Description}}", |
|||
"title": "{{.Title}}", |
|||
"contact": {}, |
|||
"license": {}, |
|||
"version": "{{.Version}}" |
|||
}, |
|||
"host": "{{.Host}}", |
|||
"basePath": "{{.BasePath}}", |
|||
"schemes": {{ marshal .Schemes }}, |
|||
"paths": { |
|||
"/api/v1/users": { |
|||
"get": { |
|||
"tags": [ |
|||
"users" |
|||
], |
|||
"summary": "获取用户列表", |
|||
"description": "返回所有用户", |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "OK", |
|||
"schema": { |
|||
"type": "array", |
|||
"items": { |
|||
"$ref": "#/definitions/model.User" |
|||
} |
|||
} |
|||
}, |
|||
"500": { |
|||
"description": "Internal Server Error", |
|||
"schema": { |
|||
"$ref": "#/definitions/http.ErrorResponse" |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"post": { |
|||
"tags": [ |
|||
"users" |
|||
], |
|||
"summary": "创建用户", |
|||
"description": "创建新的用户记录", |
|||
"consumes": [ |
|||
"application/json" |
|||
], |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"parameters": [ |
|||
{ |
|||
"description": "用户数据", |
|||
"name": "user", |
|||
"in": "body", |
|||
"required": true, |
|||
"schema": { |
|||
"$ref": "#/definitions/model.User" |
|||
} |
|||
} |
|||
], |
|||
"responses": { |
|||
"201": { |
|||
"description": "Created", |
|||
"schema": { |
|||
"$ref": "#/definitions/model.User" |
|||
} |
|||
}, |
|||
"400": { |
|||
"description": "Bad Request", |
|||
"schema": { |
|||
"$ref": "#/definitions/http.ErrorResponse" |
|||
} |
|||
}, |
|||
"500": { |
|||
"description": "Internal Server Error", |
|||
"schema": { |
|||
"$ref": "#/definitions/http.ErrorResponse" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"/api/v1/users/{id}": { |
|||
"get": { |
|||
"tags": [ |
|||
"users" |
|||
], |
|||
"summary": "获取指定用户", |
|||
"description": "根据用户 ID 获取详情", |
|||
"produces": [ |
|||
"application/json" |
|||
], |
|||
"parameters": [ |
|||
{ |
|||
"type": "integer", |
|||
"format": "int64", |
|||
"description": "用户 ID", |
|||
"name": "id", |
|||
"in": "path", |
|||
"required": true |
|||
} |
|||
], |
|||
"responses": { |
|||
"200": { |
|||
"description": "OK", |
|||
"schema": { |
|||
"$ref": "#/definitions/model.User" |
|||
} |
|||
}, |
|||
"400": { |
|||
"description": "Bad Request", |
|||
"schema": { |
|||
"$ref": "#/definitions/http.ErrorResponse" |
|||
} |
|||
}, |
|||
"404": { |
|||
"description": "Not Found", |
|||
"schema": { |
|||
"$ref": "#/definitions/http.ErrorResponse" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}, |
|||
"definitions": { |
|||
"http.ErrorResponse": { |
|||
"type": "object", |
|||
"properties": { |
|||
"error": { |
|||
"type": "string" |
|||
} |
|||
} |
|||
}, |
|||
"model.User": { |
|||
"type": "object", |
|||
"properties": { |
|||
"ID": { |
|||
"type": "integer", |
|||
"format": "int64" |
|||
}, |
|||
"CreatedAt": { |
|||
"type": "string", |
|||
"format": "date-time" |
|||
}, |
|||
"UpdatedAt": { |
|||
"type": "string", |
|||
"format": "date-time" |
|||
}, |
|||
"DeletedAt": { |
|||
"type": "string", |
|||
"format": "date-time" |
|||
}, |
|||
"name": { |
|||
"type": "string" |
|||
}, |
|||
"email": { |
|||
"type": "string" |
|||
} |
|||
} |
|||
} |
|||
} |
|||
}` |
|||
|
|||
type swaggerInfo struct { |
|||
Version string |
|||
Host string |
|||
BasePath string |
|||
Schemes []string |
|||
Title string |
|||
Description string |
|||
} |
|||
|
|||
// SwaggerInfo holds exported Swagger Info so clients can modify it
|
|||
var SwaggerInfo = swaggerInfo{ |
|||
Version: "1.0", |
|||
Host: "", |
|||
BasePath: "/api/v1", |
|||
Schemes: []string{"http"}, |
|||
Title: "Aurora Service API", |
|||
Description: "Aurora Golang 示例 REST API,基于 Gin + GORM。", |
|||
} |
|||
|
|||
type s struct{} |
|||
|
|||
func (s *s) ReadDoc() string { |
|||
doc := docTemplate |
|||
doc = strings.Replace(doc, "{{.Version}}", SwaggerInfo.Version, -1) |
|||
doc = strings.Replace(doc, "{{.Host}}", SwaggerInfo.Host, -1) |
|||
doc = strings.Replace(doc, "{{.BasePath}}", SwaggerInfo.BasePath, -1) |
|||
doc = strings.Replace(doc, "{{.Title}}", SwaggerInfo.Title, -1) |
|||
doc = strings.Replace(doc, "{{.Description}}", SwaggerInfo.Description, -1) |
|||
doc = strings.Replace(doc, "{{ marshal .Schemes }}", marshal(SwaggerInfo.Schemes), -1) |
|||
return doc |
|||
} |
|||
|
|||
func marshal(v interface{}) string { |
|||
if v == nil { |
|||
return "[]" |
|||
} |
|||
|
|||
b, err := json.Marshal(v) |
|||
if err != nil { |
|||
return "[]" |
|||
} |
|||
|
|||
return strings.ReplaceAll(string(b), `\u0026`, "&") |
|||
} |
|||
|
|||
func init() { |
|||
swag.Register(swag.Name, &s{}) |
|||
} |
|||
|
|||
|
|||
@ -1,17 +0,0 @@ |
|||
module auroragolang |
|||
|
|||
go 1.22 |
|||
|
|||
require ( |
|||
github.com/gin-gonic/gin v1.10.0 |
|||
github.com/swaggo/files v1.1.3 |
|||
github.com/swaggo/gin-swagger v1.6.0 |
|||
github.com/swaggo/swag v1.16.3 |
|||
github.com/joho/godotenv v1.5.1 |
|||
github.com/spf13/viper v1.18.2 |
|||
gorm.io/driver/mysql v1.5.7 |
|||
gorm.io/driver/postgres v1.5.8 |
|||
gorm.io/driver/sqlite v1.5.6 |
|||
gorm.io/gorm v1.25.7-0.20240204074919-46816ad31dde |
|||
) |
|||
|
|||
@ -1,80 +0,0 @@ |
|||
package config |
|||
|
|||
import ( |
|||
"fmt" |
|||
"path/filepath" |
|||
"strings" |
|||
|
|||
"github.com/joho/godotenv" |
|||
"github.com/spf13/viper" |
|||
) |
|||
|
|||
type AppConfig struct { |
|||
Name string `mapstructure:"name"` |
|||
Env string `mapstructure:"env"` |
|||
Port int `mapstructure:"port"` |
|||
} |
|||
|
|||
type SQLiteConfig struct { |
|||
Path string `mapstructure:"path"` |
|||
} |
|||
|
|||
type MySQLConfig struct { |
|||
Host string `mapstructure:"host"` |
|||
Port int `mapstructure:"port"` |
|||
User string `mapstructure:"user"` |
|||
Password string `mapstructure:"password"` |
|||
DBName string `mapstructure:"dbname"` |
|||
Params string `mapstructure:"params"` |
|||
} |
|||
|
|||
type PostgresConfig struct { |
|||
Host string `mapstructure:"host"` |
|||
Port int `mapstructure:"port"` |
|||
User string `mapstructure:"user"` |
|||
Password string `mapstructure:"password"` |
|||
DBName string `mapstructure:"dbname"` |
|||
SSLMode string `mapstructure:"sslmode"` |
|||
} |
|||
|
|||
type DatabaseConfig struct { |
|||
Driver string `mapstructure:"driver"` |
|||
SQLite SQLiteConfig `mapstructure:"sqlite"` |
|||
MySQL MySQLConfig `mapstructure:"mysql"` |
|||
Postgres PostgresConfig `mapstructure:"postgres"` |
|||
} |
|||
|
|||
type Config struct { |
|||
App AppConfig `mapstructure:"app"` |
|||
Database DatabaseConfig `mapstructure:"database"` |
|||
} |
|||
|
|||
func LoadConfig(configPath string) (*Config, error) { |
|||
v := viper.New() |
|||
|
|||
envPath := filepath.Join(configPath, ".env") |
|||
_ = godotenv.Load(envPath) // ignore missing .env
|
|||
|
|||
v.AddConfigPath(configPath) |
|||
v.SetConfigName("config") |
|||
v.SetConfigType("yaml") |
|||
|
|||
v.SetEnvKeyReplacer(strings.NewReplacer(".", "_")) |
|||
v.AutomaticEnv() |
|||
|
|||
if err := v.ReadInConfig(); err != nil { |
|||
return nil, fmt.Errorf("读取配置失败: %w", err) |
|||
} |
|||
|
|||
cfg := new(Config) |
|||
if err := v.Unmarshal(cfg); err != nil { |
|||
return nil, fmt.Errorf("解析配置失败: %w", err) |
|||
} |
|||
|
|||
if strings.TrimSpace(cfg.Database.Driver) == "" { |
|||
cfg.Database.Driver = "sqlite" |
|||
} |
|||
|
|||
return cfg, nil |
|||
} |
|||
|
|||
@ -1,10 +0,0 @@ |
|||
package model |
|||
|
|||
import "gorm.io/gorm" |
|||
|
|||
type User struct { |
|||
gorm.Model |
|||
Name string `json:"name" gorm:"size:255;not null"` |
|||
Email string `json:"email" gorm:"size:255;uniqueIndex;not null"` |
|||
} |
|||
|
|||
@ -1,10 +0,0 @@ |
|||
package repository |
|||
|
|||
import "auroragolang/internal/domain/model" |
|||
|
|||
type UserRepository interface { |
|||
List() ([]model.User, error) |
|||
GetByID(id uint) (*model.User, error) |
|||
Create(user *model.User) error |
|||
} |
|||
|
|||
@ -1,55 +0,0 @@ |
|||
package database |
|||
|
|||
import ( |
|||
"fmt" |
|||
"os" |
|||
"path/filepath" |
|||
"strings" |
|||
|
|||
"auroragolang/internal/config" |
|||
|
|||
"gorm.io/driver/mysql" |
|||
"gorm.io/driver/postgres" |
|||
"gorm.io/driver/sqlite" |
|||
"gorm.io/gorm" |
|||
) |
|||
|
|||
func Connect(cfg config.DatabaseConfig) (*gorm.DB, error) { |
|||
driver := strings.ToLower(cfg.Driver) |
|||
switch driver { |
|||
case "sqlite": |
|||
dbPath := cfg.SQLite.Path |
|||
if !filepath.IsAbs(dbPath) { |
|||
dbPath = filepath.Join(".", dbPath) |
|||
} |
|||
if err := os.MkdirAll(filepath.Dir(dbPath), 0o755); err != nil { |
|||
return nil, fmt.Errorf("创建SQLite目录失败: %w", err) |
|||
} |
|||
return gorm.Open(sqlite.Open(dbPath), &gorm.Config{}) |
|||
case "mysql": |
|||
dsn := fmt.Sprintf( |
|||
"%s:%s@tcp(%s:%d)/%s?%s", |
|||
cfg.MySQL.User, |
|||
cfg.MySQL.Password, |
|||
cfg.MySQL.Host, |
|||
cfg.MySQL.Port, |
|||
cfg.MySQL.DBName, |
|||
cfg.MySQL.Params, |
|||
) |
|||
return gorm.Open(mysql.Open(dsn), &gorm.Config{}) |
|||
case "postgres", "postgresql": |
|||
dsn := fmt.Sprintf( |
|||
"host=%s port=%d user=%s password=%s dbname=%s sslmode=%s", |
|||
cfg.Postgres.Host, |
|||
cfg.Postgres.Port, |
|||
cfg.Postgres.User, |
|||
cfg.Postgres.Password, |
|||
cfg.Postgres.DBName, |
|||
cfg.Postgres.SSLMode, |
|||
) |
|||
return gorm.Open(postgres.Open(dsn), &gorm.Config{}) |
|||
default: |
|||
return nil, fmt.Errorf("未知的数据库驱动: %s", cfg.Driver) |
|||
} |
|||
} |
|||
|
|||
@ -1,37 +0,0 @@ |
|||
package repository |
|||
|
|||
import ( |
|||
"auroragolang/internal/domain/model" |
|||
domainRepo "auroragolang/internal/domain/repository" |
|||
|
|||
"gorm.io/gorm" |
|||
) |
|||
|
|||
type GormUserRepository struct { |
|||
db *gorm.DB |
|||
} |
|||
|
|||
func NewGormUserRepository(db *gorm.DB) domainRepo.UserRepository { |
|||
return &GormUserRepository{db: db} |
|||
} |
|||
|
|||
func (r *GormUserRepository) List() ([]model.User, error) { |
|||
var users []model.User |
|||
if err := r.db.Find(&users).Error; err != nil { |
|||
return nil, err |
|||
} |
|||
return users, nil |
|||
} |
|||
|
|||
func (r *GormUserRepository) GetByID(id uint) (*model.User, error) { |
|||
var user model.User |
|||
if err := r.db.First(&user, id).Error; err != nil { |
|||
return nil, err |
|||
} |
|||
return &user, nil |
|||
} |
|||
|
|||
func (r *GormUserRepository) Create(user *model.User) error { |
|||
return r.db.Create(user).Error |
|||
} |
|||
|
|||
@ -1,28 +0,0 @@ |
|||
package http |
|||
|
|||
import ( |
|||
"auroragolang/internal/usecase" |
|||
|
|||
swaggerFiles "github.com/swaggo/files" |
|||
ginSwagger "github.com/swaggo/gin-swagger" |
|||
|
|||
"github.com/gin-gonic/gin" |
|||
) |
|||
|
|||
func NewRouter(userService *usecase.UserService) *gin.Engine { |
|||
router := gin.Default() |
|||
|
|||
userHandler := NewUserHandler(userService) |
|||
|
|||
router.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)) |
|||
|
|||
api := router.Group("/api/v1") |
|||
{ |
|||
api.GET("/users", userHandler.ListUsers) |
|||
api.GET("/users/:id", userHandler.GetUser) |
|||
api.POST("/users", userHandler.CreateUser) |
|||
} |
|||
|
|||
return router |
|||
} |
|||
|
|||
@ -1,94 +0,0 @@ |
|||
package http |
|||
|
|||
import ( |
|||
"net/http" |
|||
"strconv" |
|||
|
|||
"auroragolang/internal/domain/model" |
|||
"auroragolang/internal/usecase" |
|||
|
|||
"github.com/gin-gonic/gin" |
|||
) |
|||
|
|||
type UserHandler struct { |
|||
service *usecase.UserService |
|||
} |
|||
|
|||
type ErrorResponse struct { |
|||
Error string `json:"error"` |
|||
} |
|||
|
|||
func NewUserHandler(service *usecase.UserService) *UserHandler { |
|||
return &UserHandler{service: service} |
|||
} |
|||
|
|||
// ListUsers godoc
|
|||
// @Summary 获取用户列表
|
|||
// @Description 返回所有用户
|
|||
// @Tags users
|
|||
// @Produce json
|
|||
// @Success 200 {array} model.User
|
|||
// @Failure 500 {object} ErrorResponse
|
|||
// @Router /api/v1/users [get]
|
|||
func (h *UserHandler) ListUsers(c *gin.Context) { |
|||
users, err := h.service.ListUsers() |
|||
if err != nil { |
|||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) |
|||
return |
|||
} |
|||
c.JSON(http.StatusOK, users) |
|||
} |
|||
|
|||
// GetUser godoc
|
|||
// @Summary 获取指定用户
|
|||
// @Description 根据用户 ID 获取详情
|
|||
// @Tags users
|
|||
// @Produce json
|
|||
// @Param id path int true "用户 ID"
|
|||
// @Success 200 {object} model.User
|
|||
// @Failure 400 {object} ErrorResponse
|
|||
// @Failure 404 {object} ErrorResponse
|
|||
// @Router /api/v1/users/{id} [get]
|
|||
func (h *UserHandler) GetUser(c *gin.Context) { |
|||
idParam := c.Param("id") |
|||
id, err := strconv.Atoi(idParam) |
|||
if err != nil { |
|||
c.JSON(http.StatusBadRequest, gin.H{"error": "无效的用户ID"}) |
|||
return |
|||
} |
|||
|
|||
user, err := h.service.GetUser(uint(id)) |
|||
if err != nil { |
|||
c.JSON(http.StatusNotFound, gin.H{"error": err.Error()}) |
|||
return |
|||
} |
|||
|
|||
c.JSON(http.StatusOK, user) |
|||
} |
|||
|
|||
// CreateUser godoc
|
|||
// @Summary 创建用户
|
|||
// @Description 创建新的用户记录
|
|||
// @Tags users
|
|||
// @Accept json
|
|||
// @Produce json
|
|||
// @Param user body model.User true "用户数据"
|
|||
// @Success 201 {object} model.User
|
|||
// @Failure 400 {object} ErrorResponse
|
|||
// @Failure 500 {object} ErrorResponse
|
|||
// @Router /api/v1/users [post]
|
|||
func (h *UserHandler) CreateUser(c *gin.Context) { |
|||
var payload model.User |
|||
if err := c.ShouldBindJSON(&payload); err != nil { |
|||
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) |
|||
return |
|||
} |
|||
|
|||
if err := h.service.CreateUser(&payload); err != nil { |
|||
c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()}) |
|||
return |
|||
} |
|||
|
|||
c.JSON(http.StatusCreated, payload) |
|||
} |
|||
|
|||
@ -1,27 +0,0 @@ |
|||
package usecase |
|||
|
|||
import ( |
|||
"auroragolang/internal/domain/model" |
|||
"auroragolang/internal/domain/repository" |
|||
) |
|||
|
|||
type UserService struct { |
|||
repo repository.UserRepository |
|||
} |
|||
|
|||
func NewUserService(repo repository.UserRepository) *UserService { |
|||
return &UserService{repo: repo} |
|||
} |
|||
|
|||
func (s *UserService) ListUsers() ([]model.User, error) { |
|||
return s.repo.List() |
|||
} |
|||
|
|||
func (s *UserService) GetUser(id uint) (*model.User, error) { |
|||
return s.repo.GetByID(id) |
|||
} |
|||
|
|||
func (s *UserService) CreateUser(user *model.User) error { |
|||
return s.repo.Create(user) |
|||
} |
|||
|
|||
@ -1,8 +0,0 @@ |
|||
# 修改记录 |
|||
|
|||
- 2025-11-11:创建 Aurora Golang Clean 架构项目模板,新增多数据库配置、Gin/GORM 依赖注入、示例 User 用例以及 README 文档。 |
|||
- 2025-11-11:新增 `docs/architecture.md` 描述架构与数据库切换、自动迁移等能力,便于核对需求符合情况。 |
|||
- 2025-11-11:新增 `docs/code_structure.md` 输出项目代码目录树,方便快速浏览模块。 |
|||
- 2025-11-11:调整配置加载逻辑,默认使用 SQLite;同步更新架构文档说明。 |
|||
- 2025-11-11:集成 Swaggo,新增 `/swagger` 接口文档路由与 `docs/docs.go` 描述文件,并补充相关文档。 |
|||
|
|||
@ -1,18 +0,0 @@ |
|||
package logger |
|||
|
|||
import ( |
|||
"log" |
|||
"os" |
|||
) |
|||
|
|||
type Logger struct { |
|||
*log.Logger |
|||
} |
|||
|
|||
func New(appName string) *Logger { |
|||
prefix := appName + " " |
|||
return &Logger{ |
|||
Logger: log.New(os.Stdout, prefix, log.LstdFlags|log.Lshortfile), |
|||
} |
|||
} |
|||
|
|||
Loading…
Reference in new issue