好,既然你想用 Java Spring Boot 的套路来对齐 Go 的分层架构,那我就用对照 + 映射 + 示例代码的方式,把这套东西讲清楚。
你只要记住一句话:
Spring Boot 的分层,几乎可以 1:1 映射到 Go,只是“依赖注入”和“接口”这块 Go 更轻量。
一、整体架构对照(核心)
| 层级 | Spring Boot | Go(Gin 为例) | 职责 |
|---|---|---|---|
| 入口 | Controller |
Handler |
接收请求、参数校验、返回响应 |
| 业务 | Service + @Transactional |
Service |
业务逻辑、事务、编排 |
| 数据 | Repository / Mapper |
Repository |
CRUD、SQL |
| 模型 | Entity / DTO |
Model / Struct |
数据结构 |
| 配置 | @Configuration |
wire / 手动注入 |
依赖组装 |
| 路由 | @RequestMapping |
router.go |
URL → Handler |
✅ 结论:Go 完全可以写出“Spring Boot 味”的项目结构。
二、目录结构对照(强烈建议照着建)
✅ Spring Boot
controller/service/repository/entity/config/resources/templates/
✅ Go(Gin)
handler/service/repository/model/router/config/templates/
几乎一模一样 👍
这就是 Go 的“企业级写法”。
三、逐层对照 + 示例代码
1️⃣ Controller / Handler(入口层)
✅ Spring Boot
@RestController@RequestMapping("/articles")public class ArticleController {@Autowiredprivate ArticleService articleService;@GetMapping("/{id}")public Article getArticle(@PathVariable String id) {return articleService.getById(id);}}
✅ Go(Gin)
func RegisterRoutes(r *gin.Engine, svc *ArticleService) {h := &ArticleHandler{svc: svc}r.GET("/articles/:id", h.GetByID)}type ArticleHandler struct {svc *ArticleService}func (h *ArticleHandler) GetByID(c *gin.Context) {id := c.Param("id")article, err := h.svc.GetByID(id)if err != nil {c.JSON(500, gin.H{"error": err.Error()})return}c.JSON(200, article)}
✅ 一一对应:
@RequestMapping→router.go@Autowired→ 构造函数注入@GetMapping→r.GET(...)
2️⃣ Service(业务层)
✅ Spring Boot
@Servicepublic class ArticleService {@Autowiredprivate ArticleRepository repository;@Transactionalpublic Article getById(String id) {return repository.findById(id);}}
✅ Go
type ArticleService struct {repo *ArticleRepository}func NewArticleService(repo *ArticleRepository) *ArticleService {return &ArticleService{repo: repo}}func (s *ArticleService) GetByID(id string) (*Article, error) {if id == "" {return nil, errors.New("id is empty")}return s.repo.FindByID(id)}
✅ 对应点:
@Service→ 结构体 +NewXXX@Transactional→ 手动tx(Go 没有声明式事务)- 业务规则 → 全放 Service
3️⃣ Repository(数据层)
✅ Spring Boot
@Repositorypublic interface ArticleRepository {Article findById(String id);}
✅ Go
type ArticleRepository struct {db *gorm.DB}func NewArticleRepository(db *gorm.DB) *ArticleRepository {return &ArticleRepository{db: db}}func (r *ArticleRepository) FindByID(id string) (*Article, error) {var article Articleerr := r.db.Where("id = ?", id).First(&article).Errorreturn &article, err}
✅ 只做 CRUD,不写业务,和 Spring 的 Repository 完全一致。
4️⃣ Model / Entity
✅ Spring Boot
@Entitypublic class Article {private String id;private String title;}
✅ Go
type Article struct {ID string `json:"id"`Title string `json:"title"`}
✅ Go 的 struct = Java 的 entity / POJO
四、依赖注入(DI)对照(重点)
| Spring Boot | Go |
|---|---|
@Autowired |
构造函数参数 |
@ComponentScan |
手动 NewXXX(...) |
| IoC 容器 | wire(推荐)/ 手写 |
✅ Go 的“伪 DI”(非常 Spring)
db := initDB()repo := NewArticleRepository(db)service := NewArticleService(repo)handler := NewArticleHandler(service)RegisterRoutes(router, handler)
👉 这就是 Go 的“控制反转”,不靠框架,靠代码清晰。
五、事务怎么写?(Go ≠ Spring)
Spring:
@Transactionalpublic void update() {}
Go:
func (s *ArticleService) Update() error {tx := s.repo.db.Begin()defer tx.Rollback()// 业务逻辑return tx.Commit().Error}
✅ Go 没有 AOP,事务必须“显式写”,这也是 Go 的风格。
六、一句话总结这套映射
Spring Boot 是“框架帮你分层”,Go 是“你自己把分层写清楚”。
但只要你按Handler → Service → Repository走,
Go 项目就可以拥有 Spring Boot 一样的工程化结构。
七、你现在最值得做的事
如果你是从 PHP → Go + 想对 Java 平滑过渡,我建议你现在就:
- ✅ 用这套结构写一个 最小可用项目
- ✅ 刻意练习:Handler 不写 SQL
- ✅ 用
wire或手写 DI,模拟 Spring 的注入 - ✅ SEO 页面用
html/template,API 用JSON
