项目结构
推荐的 VEF Framework 项目目录结构。
标准项目结构
my-app/
├── cmd/
│ └── server/
│ └── main.go # 应用入口
├── config/
│ ├── config.yaml # 默认配置
│ ├── config.dev.yaml # 开发环境配置
│ └── config.prod.yaml # 生产环境配置
├── internal/
│ ├── buildinfo/
│ │ └── info.go # 构建信息(自动生成)
│ ├── modules/
│ │ ├── user/ # 用户模块
│ │ │ ├── models/
│ │ │ │ └── user.go
│ │ │ ├── payloads/
│ │ │ │ ├── search.go
│ │ │ │ └── params.go
│ │ │ ├── resources/
│ │ │ │ └── user_resource.go
│ │ │ └── module.go
│ │ └── order/ # 订单模块
│ │ ├── models/
│ │ ├── payloads/
│ │ ├── resources/
│ │ └── module.go
│ ├── services/ # 共享服务
│ │ ├── email_service.go
│ │ └── sms_service.go
│ ├── middleware/ # 自定义中间件
│ │ └── tenant.go
│ └── app.go # 应用配置
├── pkg/ # 可复用的包
│ └── utils/
├── migrations/ # 数据库迁移
├── docs/ # API 文档
├── scripts/ # 脚本文件
├── go.mod
├── go.sum
├── Makefile
└── README.md模块结构
每个业务模块包含以下子目录:
modules/user/
├── models/ # 数据模型
│ ├── user.go
│ └── user_role.go
├── payloads/ # 请求/响应参数
│ ├── search.go # 搜索参数
│ └── params.go # 创建/更新参数
├── resources/ # API 资源
│ └── user_resource.go
├── services/ # 模块内服务(可选)
│ └── user_service.go
├── events/ # 事件定义(可选)
│ └── user_events.go
├── jobs/ # 定时任务(可选)
│ └── cleanup_job.go
└── module.go # 模块定义模块定义示例
go
// internal/modules/user/module.go
package user
import (
"my-app/internal/modules/user/resources"
"go.uber.org/fx"
)
func Module() fx.Option {
return fx.Options(
fx.Provide(
resources.NewUserResource,
resources.NewRoleResource,
),
)
}应用入口
go
// cmd/server/main.go
package main
import (
"my-app/internal"
"my-app/internal/modules/user"
"my-app/internal/modules/order"
"go.uber.org/fx"
)
func main() {
app := fx.New(
// Core infrastructure
internal.CoreModule(),
// Business modules
user.Module(),
order.Module(),
// Start HTTP server
fx.Invoke(internal.StartServer),
)
app.Run()
}核心模块
go
// internal/app.go
package internal
import (
"github.com/ilxqx/vef-framework-go/config"
"github.com/ilxqx/vef-framework-go/orm"
"github.com/ilxqx/vef-framework-go/cache"
"go.uber.org/fx"
)
func CoreModule() fx.Option {
return fx.Options(
fx.Provide(
config.Load,
orm.NewDB,
cache.NewCache,
),
)
}
func StartServer(lc fx.Lifecycle, cfg *config.Config) {
// Initialize and start HTTP server
}模型文件
go
// internal/modules/user/models/user.go
package models
import (
"github.com/ilxqx/vef-framework-go/orm"
"github.com/ilxqx/vef-framework-go/null"
)
type User struct {
orm.Model
Username string `gorm:"size:50;uniqueIndex;not null" json:"username"`
Email string `gorm:"size:100;not null" json:"email"`
Password string `gorm:"size:255;not null" json:"-"`
IsActive bool `gorm:"default:true" json:"isActive"`
DepartmentId null.String `gorm:"size:36" json:"departmentId"`
// Relations
Department *Department `gorm:"foreignKey:DepartmentId" json:"department,omitempty"`
Roles []Role `gorm:"many2many:user_roles" json:"roles,omitempty"`
}参数文件
go
// internal/modules/user/payloads/search.go
package payloads
type UserSearch struct {
Username string `search:"like"`
Email string `search:"like"`
IsActive *bool `search:"eq"`
DepartmentId string `search:"eq"`
CreatedFrom string `search:"gte" column:"created_at"`
CreatedTo string `search:"lte" column:"created_at"`
}
// internal/modules/user/payloads/params.go
package payloads
type UserCreateParams struct {
Username string `json:"username" validate:"required,min=3,max=50"`
Email string `json:"email" validate:"required,email"`
Password string `json:"password" validate:"required,min=8"`
DepartmentId string `json:"departmentId"`
}
type UserUpdateParams struct {
Username string `json:"username" validate:"omitempty,min=3,max=50"`
Email string `json:"email" validate:"omitempty,email"`
DepartmentId string `json:"departmentId"`
IsActive *bool `json:"isActive"`
}资源文件
go
// internal/modules/user/resources/user_resource.go
package resources
import (
"my-app/internal/modules/user/models"
"my-app/internal/modules/user/payloads"
"github.com/ilxqx/vef-framework-go/api"
"github.com/ilxqx/vef-framework-go/apis"
)
type UserResource struct {
api.Resource
apis.FindPageApi[models.User, payloads.UserSearch]
apis.CreateApi[models.User, payloads.UserCreateParams]
apis.UpdateApi[models.User, payloads.UserUpdateParams]
apis.DeleteApi[models.User]
}
func NewUserResource() api.Resource {
return &UserResource{
Resource: api.NewResource("smp/sys/user"),
FindPageApi: apis.NewFindPageApi[models.User, payloads.UserSearch](),
CreateApi: apis.NewCreateApi[models.User, payloads.UserCreateParams](),
UpdateApi: apis.NewUpdateApi[models.User, payloads.UserUpdateParams](),
DeleteApi: apis.NewDeleteApi[models.User](),
}
}