The Go-API framework includes a powerful code generator that automatically creates Go models and repositories from MySQL CREATE TABLE statements. This tool significantly speeds up development by eliminating boilerplate code and ensuring consistency across your data layer.
- SQL Parsing: Supports complex field type definitions (VARCHAR(255), DECIMAL(10,2), etc.)
- Type Mapping: Comprehensive mapping from MySQL types to Go types
- GORM Integration: Automatic generation of GORM tags (column, size, not null, default, etc.)
- Comment Support: Preserves SQL comments as Go struct field comments
- Repository Generation: Automatic generation of repository interfaces and implementations
- Smart Update Logic: Generates update methods that only update non-zero fields
- Flexible List Methods: List methods that accept struct parameters for query conditions
- Batch Processing: Process single files or entire directories
- Force Overwrite: Option to overwrite existing files
# Build the code generator
go build -o codegen ./command/codegen/handler.go./codegen [options]Available Options:
-force: Force overwrite existing files (default: false)-name: SQL file name (without .sql extension) to generate code for-sql: SQL directory path (default: "bin/data/sql")-model: Model output directory (default: "app/model")-repo: Repository output directory (default: "app/repository")-service: Service output directory (default: "app/service")
Generate code for a single SQL file:
./codegen -name auth_appGenerate code for all SQL files in directory:
./codegenUse custom paths:
./codegen -sql custom/sql/path -model custom/model/path -forceGenerate with all options:
./codegen -name users -sql bin/data/sql -model app/model -repo app/repository -service app/service -forceThe generator expects standard MySQL CREATE TABLE statements. Here's a comprehensive example:
CREATE TABLE `auth_app`
(
`id` int NOT NULL AUTO_INCREMENT COMMENT 'Primary Key',
`app_id` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'Application ID',
`app_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT 'Application Name',
`app_secret` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT 'Application Secret',
`redirect_uri` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT 'Redirect URI',
`description` text COMMENT 'Description',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT 'Status: 0=Inactive, 1=Active, 2=Disabled',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_app_id` (`app_id`),
KEY `idx_status` (`status`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = 'Application Information Table';The generator maps MySQL types to appropriate Go types:
| MySQL Type | Go Type | GORM Tag Example |
|---|---|---|
int, integer |
int |
gorm:"column:id;not null" |
tinyint |
int8 |
gorm:"column:status;not null;default:0" |
smallint |
int16 |
gorm:"column:count;not null" |
bigint |
int64 |
gorm:"column:large_id;not null" |
varchar(n), char(n) |
string |
gorm:"column:name;size:50;not null" |
text, longtext |
string |
gorm:"column:description;type:text" |
decimal(m,n), numeric(m,n) |
float64 |
gorm:"column:price;type:decimal(10,2)" |
float |
float32 |
gorm:"column:rate;type:float" |
double |
float64 |
gorm:"column:amount;type:double" |
timestamp, datetime |
time.Time |
gorm:"column:created_at" |
date |
time.Time |
gorm:"column:birth_date;type:date" |
json |
string |
gorm:"column:data;type:json" |
blob |
[]byte |
gorm:"column:content;type:blob" |
The generator creates comprehensive model files with:
- Proper Go naming conventions (snake_case → CamelCase)
- GORM tags for database mapping
- JSON tags for API serialization
- Field comments from SQL comments
- Common database methods (CRUD operations)
Example Generated Model:
package auth
import (
"context"
"errors"
"fmt"
"gorm.io/gorm"
)
type App struct {
gorm.Model
AppId string `gorm:"column:app_id;size:30;not null" json:"app_id"` // Application ID
AppName string `gorm:"column:app_name;size:50" json:"app_name"` // Application Name
AppSecret string `gorm:"column:app_secret;size:256;not null" json:"app_secret"` // Application Secret
RedirectUri string `gorm:"column:redirect_uri;size:500" json:"redirect_uri"` // Redirect URI
Description string `gorm:"column:description;type:text" json:"description"` // Description
Status int8 `gorm:"column:status;not null;default:0" json:"status"` // Status: 0=Inactive, 1=Active, 2=Disabled
// Query conditions for chaining methods
queryCondition interface{} `gorm:"-" json:"-"`
queryArgs []interface{} `gorm:"-" json:"-"`
}
// TableName specifies the table name for the App model.
func (a *App) TableName() string {
return "auth_app"
}
// Where sets query conditions for chaining with other methods.
func (a *App) Where(query interface{}, args ...interface{}) *App {
newApp := *a
newApp.queryCondition = query
newApp.queryArgs = args
return &newApp
}
// First retrieves the first app matching the criteria from the database.
func (a *App) First(ctx context.Context, db *gorm.DB) (*App, error) {
var app App
query := db.WithContext(ctx)
// Apply Where conditions if set
if a.queryCondition != nil {
query = query.Where(a.queryCondition, a.queryArgs...)
} else {
query = query.Where(a)
}
if err := query.First(&app).Error; err != nil {
if errors.Is(err, gorm.ErrRecordNotFound) {
return nil, nil
}
return nil, fmt.Errorf("find first failed: %w", err)
}
return &app, nil
}
// Create inserts a new app into the database and returns the ID.
func (a *App) Create(ctx context.Context, db *gorm.DB) (uint, error) {
if err := db.WithContext(ctx).Create(a).Error; err != nil {
return 0, fmt.Errorf("create failed: %w", err)
}
return a.ID, nil
}
// Updates applies the specified updates to the app in the database.
func (a *App) Updates(ctx context.Context, db *gorm.DB, updates map[string]interface{}) error {
query := db.WithContext(ctx).Model(&App{})
if a.queryCondition != nil {
query = query.Where(a.queryCondition, a.queryArgs...)
} else if a.ID > 0 {
query = query.Where("id = ?", a.ID)
} else {
query = query.Where(a)
}
return query.Updates(updates).Error
}
// Delete removes the app from the database.
func (a *App) Delete(ctx context.Context, db *gorm.DB) error {
query := db.WithContext(ctx)
if a.queryCondition != nil {
query = query.Where(a.queryCondition, a.queryArgs...)
} else {
query = query.Where(a)
}
return query.Delete(&App{}).Error
}
// List retrieves all apps matching the criteria from the database.
func (a *App) List(ctx context.Context, db *gorm.DB) ([]App, error) {
var apps []App
query := db.WithContext(ctx)
if a.queryCondition != nil {
query = query.Where(a.queryCondition, a.queryArgs...)
} else {
query = query.Where(a)
}
if err := query.Find(&apps).Error; err != nil {
return nil, fmt.Errorf("list failed: %w", err)
}
return apps, nil
}
// Additional utility methods...The generator creates repository interfaces and implementations:
Repository Interface:
package auth
import (
"context"
"github.com/seakee/go-api/app/model/auth"
"github.com/sk-pkg/redis"
"gorm.io/gorm"
)
// AppRepo defines the interface for app-related database operations.
type AppRepo interface {
// GetApp retrieves a app by its properties.
GetApp(ctx context.Context, app *auth.App) (*auth.App, error)
// Create inserts a new app into the database.
Create(ctx context.Context, app *auth.App) (uint, error)
// Update updates an existing app in the database.
Update(ctx context.Context, id uint, app *auth.App) error
// Delete deletes a app by its ID.
Delete(ctx context.Context, id uint) error
// List retrieves app records based on query conditions.
List(ctx context.Context, app *auth.App) ([]auth.App, error)
// GetByID retrieves a app by its ID.
GetByID(ctx context.Context, id uint) (*auth.App, error)
}Repository Implementation:
// appRepo implements the AppRepo interface.
type appRepo struct {
redis *redis.Manager
db *gorm.DB
}
// NewAppRepo creates a new instance of the app repository.
func NewAppRepo(db *gorm.DB, redis *redis.Manager) AppRepo {
return &appRepo{redis: redis, db: db}
}
// Create creates a new app record using the model's Create method.
func (r *appRepo) Create(ctx context.Context, app *auth.App) (uint, error) {
return app.Create(ctx, r.db)
}
// Update updates an existing app record with smart field detection.
func (r *appRepo) Update(ctx context.Context, id uint, app *auth.App) error {
data := make(map[string]interface{})
if app.AppId != "" {
data["app_id"] = app.AppId
}
if app.AppName != "" {
data["app_name"] = app.AppName
}
if app.AppSecret != "" {
data["app_secret"] = app.AppSecret
}
if app.RedirectUri != "" {
data["redirect_uri"] = app.RedirectUri
}
if app.Description != "" {
data["description"] = app.Description
}
if app.Status != 0 {
data["status"] = app.Status
}
if len(data) == 0 {
return nil // No fields to update
}
updateModel := &auth.App{}
updateModel.ID = id
return updateModel.Updates(ctx, r.db, data)
}
// GetByID retrieves a app by its ID.
func (r *appRepo) GetByID(ctx context.Context, id uint) (*auth.App, error) {
app := &auth.App{}
return app.Where("id = ?", id).First(ctx, r.db)
}
// List retrieves app records based on query conditions.
func (r *appRepo) List(ctx context.Context, app *auth.App) ([]auth.App, error) {
return app.List(ctx, r.db)
}
// Additional methods...You can customize the generated code by modifying the templates in command/codegen/codegen/:
model.go: Contains model generation templatesrepository.go: Contains repository generation templates
The generator follows these naming conventions:
- Snake case to Camel case:
user_name→UserName - Table names: Preserved as-is for
TableName()method - Package names: Derived from directory structure
- File names: Follow Go conventions (lowercase with underscores)
The generator automatically creates appropriate GORM tags:
// VARCHAR(50) NOT NULL →
`gorm:"column:username;size:50;not null"`
// INT DEFAULT 1 →
`gorm:"column:status;not null;default:1"`
// TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP →
`gorm:"column:created_at"`SQL comments are converted to Go comments:
`username` varchar(50) NOT NULL COMMENT 'User login name'Becomes:
Username string `gorm:"column:username;size:50;not null" json:"username"` // User login name// Create a new app
app := &auth.App{
AppId: "app123",
AppName: "My Application",
AppSecret: "secret123",
Status: 1,
}
id, err := app.Create(ctx, db)
if err != nil {
log.Fatal(err)
}
// Query apps
searchApp := &auth.App{Status: 1}
apps, err := searchApp.List(ctx, db)
if err != nil {
log.Fatal(err)
}
// Update with Where condition
updateApp := &auth.App{}
updates := map[string]interface{}{
"app_name": "Updated Name",
"status": 2,
}
err = updateApp.Where("app_id = ?", "app123").Updates(ctx, db, updates)// Initialize repository
repo := auth.NewAppRepo(db, redisManager)
// Use repository methods
app := &auth.App{
AppName: "New App",
Status: 1,
}
id, err := repo.Create(ctx, app)
if err != nil {
log.Fatal(err)
}
// Get by ID
foundApp, err := repo.GetByID(ctx, id)
if err != nil {
log.Fatal(err)
}Organize your SQL files by feature or module:
bin/data/sql/
├── auth/
│ ├── auth_app.sql
│ └── auth_user.sql
├── user/
│ ├── user_profile.sql
│ └── user_setting.sql
└── order/
├── order.sql
└── order_item.sql
- Use version control to track generated code changes
- Run generation in CI/CD pipeline
- Use
-forceflag carefully in production
- Extend generated models with additional methods
- Use composition for complex business logic
- Keep generated code separate from custom code
- Parse Error: Check SQL syntax, especially CREATE TABLE statement
- Type Mapping: Verify supported MySQL types
- File Permissions: Ensure write permissions to output directories
- Import Conflicts: Check for naming conflicts with existing packages
Run generator with verbose output:
./codegen -name table_name -vIf automatic generation fails, you can:
- Fix SQL syntax issues
- Add missing table comments
- Ensure proper field types
- Check character encoding
Go-API框架包含一个强大的代码生成器,可以从MySQL CREATE TABLE语句自动创建Go模型和仓库。这个工具通过消除样板代码并确保数据层的一致性,显著加快了开发速度。
- SQL解析: 支持复杂的字段类型定义(VARCHAR(255)、DECIMAL(10,2)等)
- 类型映射: MySQL类型到Go类型的全面映射
- GORM集成: 自动生成GORM标签(column、size、not null、default等)
- 注释支持: 将SQL注释保存为Go结构体字段注释
- 仓库生成: 自动生成仓库接口和实现
- 智能更新逻辑: 生成只更新非零值字段的更新方法
- 灵活的列表方法: 接受结构体参数进行查询条件的列表方法
- 批处理: 处理单个文件或整个目录
- 强制覆盖: 覆盖现有文件的选项
# 构建代码生成器
go build -o codegen ./command/codegen/handler.go./codegen [选项]可用选项:
-force: 强制覆盖现有文件(默认:false)-name: 要生成代码的SQL文件名(不含.sql扩展名)-sql: SQL目录路径(默认:"bin/data/sql")-model: 模型输出目录(默认:"app/model")-repo: 仓库输出目录(默认:"app/repository")-service: 服务输出目录(默认:"app/service")
为单个SQL文件生成代码:
./codegen -name auth_app为目录中的所有SQL文件生成代码:
./codegen使用自定义路径:
./codegen -sql custom/sql/path -model custom/model/path -force生成器期望标准的MySQL CREATE TABLE语句。这是一个综合示例:
CREATE TABLE `auth_app`
(
`id` int NOT NULL AUTO_INCREMENT COMMENT '主键',
`app_id` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '应用ID',
`app_name` varchar(50) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '应用名称',
`app_secret` varchar(256) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NOT NULL COMMENT '应用密钥',
`redirect_uri` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci DEFAULT NULL COMMENT '重定向URI',
`description` text COMMENT '描述',
`status` tinyint(1) NOT NULL DEFAULT '0' COMMENT '状态:0=未激活,1=激活,2=禁用',
`created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`updated_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
`deleted_at` timestamp NULL DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `unique_app_id` (`app_id`),
KEY `idx_status` (`status`)
) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '应用信息表';生成器将MySQL类型映射到适当的Go类型:
| MySQL类型 | Go类型 | GORM标签示例 |
|---|---|---|
int, integer |
int |
gorm:"column:id;not null" |
tinyint |
int8 |
gorm:"column:status;not null;default:0" |
smallint |
int16 |
gorm:"column:count;not null" |
bigint |
int64 |
gorm:"column:large_id;not null" |
varchar(n), char(n) |
string |
gorm:"column:name;size:50;not null" |
text, longtext |
string |
gorm:"column:description;type:text" |
decimal(m,n), numeric(m,n) |
float64 |
gorm:"column:price;type:decimal(10,2)" |
float |
float32 |
gorm:"column:rate;type:float" |
double |
float64 |
gorm:"column:amount;type:double" |
timestamp, datetime |
time.Time |
gorm:"column:created_at" |
date |
time.Time |
gorm:"column:birth_date;type:date" |
json |
string |
gorm:"column:data;type:json" |
blob |
[]byte |
gorm:"column:content;type:blob" |
生成器创建包含以下内容的综合模型文件:
- 正确的Go命名约定(snake_case → CamelCase)
- GORM标签用于数据库映射
- JSON标签用于API序列化
- 来自SQL注释的字段注释
- 常见的数据库方法(CRUD操作)
您可以通过修改command/codegen/codegen/中的模板来自定义生成的代码:
model.go: 包含模型生成模板repository.go: 包含仓库生成模板
生成器遵循这些命名约定:
- 下划线转驼峰:
user_name→UserName - 表名: 在
TableName()方法中保持原样 - 包名: 从目录结构派生
- 文件名: 遵循Go约定(小写带下划线)
生成器自动创建适当的GORM标签:
// VARCHAR(50) NOT NULL →
`gorm:"column:username;size:50;not null"`
// INT DEFAULT 1 →
`gorm:"column:status;not null;default:1"`
// TIMESTAMP NULL DEFAULT CURRENT_TIMESTAMP →
`gorm:"column:created_at"`// 创建新应用
app := &auth.App{
AppId: "app123",
AppName: "我的应用",
AppSecret: "secret123",
Status: 1,
}
id, err := app.Create(ctx, db)
if err != nil {
log.Fatal(err)
}
// 查询应用
searchApp := &auth.App{Status: 1}
apps, err := searchApp.List(ctx, db)
if err != nil {
log.Fatal(err)
}// 初始化仓库
repo := auth.NewAppRepo(db, redisManager)
// 使用仓库方法
app := &auth.App{
AppName: "新应用",
Status: 1,
}
id, err := repo.Create(ctx, app)
if err != nil {
log.Fatal(err)
}按功能或模块组织SQL文件:
bin/data/sql/
├── auth/
│ ├── auth_app.sql
│ └── auth_user.sql
├── user/
│ ├── user_profile.sql
│ └── user_setting.sql
└── order/
├── order.sql
└── order_item.sql
- 使用版本控制跟踪生成的代码更改
- 在CI/CD管道中运行生成
- 在生产环境中谨慎使用
-force标志
- 解析错误: 检查SQL语法,特别是CREATE TABLE语句
- 类型映射: 验证支持的MySQL类型
- 文件权限: 确保对输出目录有写权限
- 导入冲突: 检查与现有包的命名冲突
使用详细输出运行生成器:
./codegen -name table_name -v