6.4 KiB
6.4 KiB
👨💻 开发指南
项目结构理解
tyapi-server-gin/
├── cmd/api/ # 应用入口
├── internal/ # 内部代码
│ ├── app/ # 应用层
│ ├── config/ # 配置管理
│ ├── container/ # 依赖注入
│ ├── domains/ # 业务域
│ │ └── user/ # 用户域示例
│ └── shared/ # 共享基础设施
├── pkg/ # 外部包
├── scripts/ # 脚本文件
├── test/ # 测试文件
└── docs/ # 文档目录
开发流程
1. 创建新的业务域
# 使用Makefile创建新域
make new-domain DOMAIN=product
# 手动创建目录结构
mkdir -p internal/domains/product/{entities,dto,services,repositories,handlers,routes,events}
2. 实现业务实体
创建 internal/domains/product/entities/product.go:
type Product struct {
BaseEntity
Name string `gorm:"not null;size:100"`
Description string `gorm:"size:500"`
Price float64 `gorm:"not null"`
CategoryID uint `gorm:"not null"`
}
func (p *Product) Validate() error {
if p.Name == "" {
return errors.New("产品名称不能为空")
}
if p.Price <= 0 {
return errors.New("产品价格必须大于0")
}
return nil
}
3. 定义仓储接口
创建 internal/domains/product/repositories/product_repository.go:
type ProductRepository interface {
shared.BaseRepository[entities.Product]
FindByCategory(ctx context.Context, categoryID uint) ([]*entities.Product, error)
FindByPriceRange(ctx context.Context, min, max float64) ([]*entities.Product, error)
}
4. 实现业务服务
创建 internal/domains/product/services/product_service.go:
type ProductService interface {
CreateProduct(ctx context.Context, req *dto.CreateProductRequest) (*dto.ProductResponse, error)
GetProduct(ctx context.Context, id uint) (*dto.ProductResponse, error)
UpdateProduct(ctx context.Context, id uint, req *dto.UpdateProductRequest) (*dto.ProductResponse, error)
DeleteProduct(ctx context.Context, id uint) error
}
5. 实现 HTTP 处理器
创建 internal/domains/product/handlers/product_handler.go:
func (h *ProductHandler) CreateProduct(c *gin.Context) {
var req dto.CreateProductRequest
if err := c.ShouldBindJSON(&req); err != nil {
response.Error(c, http.StatusBadRequest, "请求参数无效", err)
return
}
product, err := h.productService.CreateProduct(c.Request.Context(), &req)
if err != nil {
response.Error(c, http.StatusInternalServerError, "创建产品失败", err)
return
}
response.Success(c, product)
}
6. 配置路由
创建 internal/domains/product/routes/product_routes.go:
func RegisterProductRoutes(router shared.Router, handler *handlers.ProductHandler) {
v1 := router.Group("/api/v1")
{
products := v1.Group("/products")
{
products.POST("", handler.CreateProduct)
products.GET("/:id", handler.GetProduct)
products.PUT("/:id", handler.UpdateProduct)
products.DELETE("/:id", handler.DeleteProduct)
}
}
}
常用开发命令
# 代码格式化
make fmt
# 代码检查
make lint
# 运行测试
make test
# 测试覆盖率
make test-coverage
# 生成API文档
make docs
# 热重载开发
make dev
# 构建二进制文件
make build
# 清理临时文件
make clean
测试编写
单元测试示例
func TestProductService_CreateProduct(t *testing.T) {
// 设置测试数据
mockRepo := mocks.NewProductRepository(t)
service := services.NewProductService(mockRepo, nil)
req := &dto.CreateProductRequest{
Name: "测试产品",
Description: "测试描述",
Price: 99.99,
CategoryID: 1,
}
// 设置Mock期望
mockRepo.On("Create", mock.Anything, mock.AnythingOfType("*entities.Product")).
Return(&entities.Product{}, nil)
// 执行测试
result, err := service.CreateProduct(context.Background(), req)
// 断言结果
assert.NoError(t, err)
assert.NotNil(t, result)
assert.Equal(t, req.Name, result.Name)
}
集成测试示例
func TestProductAPI_Integration(t *testing.T) {
// 启动测试服务器
testApp := setupTestApp(t)
defer testApp.Cleanup()
// 创建测试请求
reqBody := `{"name":"测试产品","price":99.99,"category_id":1}`
req := httptest.NewRequest("POST", "/api/v1/products", strings.NewReader(reqBody))
req.Header.Set("Content-Type", "application/json")
// 执行请求
w := httptest.NewRecorder()
testApp.ServeHTTP(w, req)
// 验证响应
assert.Equal(t, http.StatusCreated, w.Code)
var response map[string]interface{}
json.Unmarshal(w.Body.Bytes(), &response)
assert.Equal(t, "success", response["status"])
}
开发规范
代码风格
- 使用
gofmt格式化代码 - 遵循 Go 命名规范
- 添加必要的注释和文档
- 函数长度不超过 50 行
Git 提交规范
# 功能开发
git commit -m "feat: 添加用户注册功能"
# 问题修复
git commit -m "fix: 修复登录验证问题"
# 文档更新
git commit -m "docs: 更新API文档"
# 重构代码
git commit -m "refactor: 重构用户服务层"
分支管理
main: 主分支,用于生产发布develop: 开发分支,用于集成测试feature/xxx: 功能分支,用于新功能开发hotfix/xxx: 热修复分支,用于紧急修复
调试技巧
使用 Delve 调试器
# 安装 Delve
go install github.com/go-delve/delve/cmd/dlv@latest
# 启动调试
dlv debug ./cmd/api/main.go
# 设置断点
(dlv) break main.main
(dlv) continue
日志调试
// 添加调试日志
logger.Debug("Processing user request",
zap.String("user_id", userID),
zap.String("action", "create_product"))
// 临时调试信息
fmt.Printf("Debug: %+v\n", debugData)
性能分析
# 启用 pprof
go tool pprof http://localhost:8080/debug/pprof/profile
# 内存分析
go tool pprof http://localhost:8080/debug/pprof/heap
# 协程分析
go tool pprof http://localhost:8080/debug/pprof/goroutine