Golang中分层结构的实现方式是否正确?

Golang中分层结构的实现方式是否正确? 大家好,

我尝试实现一个电子商务项目,在寻找一个良好的布局结构后,我发现分层结构可能适合我的项目。(为什么?因为我有一些实体,例如:Product, User, Order, Cart, Address, Media, Transaction and ....,如果我想要用领域驱动设计或六边形架构来实现这个项目,我必须在我的pkg目录中实现一个庞大的目录结构。但如果我的思路是错误的,并且要实施这个项目,请指导我找到最适合这个项目的分层结构。)

我尝试在play.golang.com上实现一个带有目录结构的项目简化模型,并与大家分享。请告诉我关于这个项目的任何方面是否有可以改进的地方。

https://play.golang.org/p/RBdQNDxZ_zP


更多关于Golang中分层结构的实现方式是否正确?的实战教程也可以访问 https://www.itying.com/category-94-b0.html

4 回复

感谢你的回复,Chris。那么,如果这个项目非常庞大,使用领域驱动六边形架构是否合适?在领域驱动六边形架构中,我们在这个链接里看到了这样的包结构:https://github.com/katzien/go-structure-examples 对于一个大型电子商务项目,使用领域驱动六边形架构以及上面分享的链接中的结构是否合适?

更多关于Golang中分层结构的实现方式是否正确?的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


如果我想用领域驱动设计或六边形架构来实现这个项目,就必须在我的 pkg 目录下实现一个庞大的目录结构。

为什么使用分层架构就需要在任何地方都创建一个庞大的目录?这个结论背后的假设是什么?这个假设真的成立吗?(而且,在这个上下文中,“庞大”具体指什么?)

总的来说,分层架构(如整洁架构、六边形架构等)始终是构建大型项目的坚实基础。

然而,如果你开始时使用扁平的项目结构,并在项目规模足够大时再将其重构为分层架构,这并没有错。

我认为如果你看看Kat的例子,你会发现并没有一个所谓的模型,例如用户本身——而是那个存在于各个包内部,例如adding/

我对六边形架构也比较陌生,所以还不太熟悉,但我相信它可能是少数几种能够支持你尝试做的事情的架构之一。至于如何构建你的具体示例,你需要看看进展如何,正如提到的,你可以从扁平结构开始,然后逐步完善,看看哪些可行/不可行。然而,在这个过程中,你可能需要重构你的应用,很可能不止一次。

顺便提一下,我看到你正在尝试构建某种REST风格的服务器,如果你还没看过,可以看看go-chi

希望这能帮到你!

这是一个很好的分层结构实现,符合Go项目的常见实践。你的目录结构清晰,分离了不同层的职责。以下是一些具体的评价和改进建议:

当前结构优点:

  1. 清晰的分层(domain、application、infrastructure)
  2. 依赖方向正确(外层依赖内层)
  3. 接口定义在domain层,实现在infrastructure层

可以改进的方面:

1. 依赖注入优化

当前在main.go中手动创建依赖,可以考虑使用wire等工具:

// cmd/main.go 改进示例
package main

import (
    "log"
    
    "your-project/application"
    "your-project/infrastructure/persistence/memory"
    "your-project/interfaces/http"
)

func main() {
    // 使用内存存储(可替换为其他实现)
    productRepo := memory.NewProductRepository()
    
    // 创建应用服务
    productService := application.NewProductService(productRepo)
    
    // 创建HTTP处理器
    productHandler := http.NewProductHandler(productService)
    
    // 启动服务器
    router := http.NewRouter(productHandler)
    log.Fatal(router.Run(":8080"))
}

2. 错误处理标准化

在domain层定义错误类型:

// domain/common/errors.go
package common

import "errors"

var (
    ErrProductNotFound = errors.New("product not found")
    ErrInvalidProduct  = errors.New("invalid product")
)

// domain/product/repository.go 中使用
type ProductRepository interface {
    FindByID(id string) (*Product, error)
    Save(product *Product) error
}

3. 增加领域事件支持

如果需要事件驱动:

// domain/common/event.go
package common

type Event interface {
    Name() string
}

type EventHandler interface {
    Handle(event Event) error
}

// domain/product/product.go
func (p *Product) UpdatePrice(newPrice float64) error {
    oldPrice := p.Price
    p.Price = newPrice
    p.Events = append(p.Events, ProductPriceChanged{
        ProductID: p.ID,
        OldPrice:  oldPrice,
        NewPrice:  newPrice,
    })
    return nil
}

4. 增加DTO用于层间数据传输

// interfaces/http/dto/product.go
package dto

type CreateProductRequest struct {
    Name        string  `json:"name" validate:"required"`
    Description string  `json:"description"`
    Price       float64 `json:"price" validate:"required,gt=0"`
    Stock       int     `json:"stock" validate:"gte=0"`
}

type ProductResponse struct {
    ID          string  `json:"id"`
    Name        string  `json:"name"`
    Description string  `json:"description"`
    Price       float64 `json:"price"`
    Stock       int     `json:"stock"`
}

5. 增加事务管理

在application层处理事务:

// application/product_service.go
type ProductService struct {
    repo        domain.ProductRepository
    txManager   persistence.TransactionManager
}

func (s *ProductService) UpdateProductWithTransaction(id string, updateFn func(*domain.Product) error) error {
    return s.txManager.Transaction(func() error {
        product, err := s.repo.FindByID(id)
        if err != nil {
            return err
        }
        
        if err := updateFn(product); err != nil {
            return err
        }
        
        return s.repo.Save(product)
    })
}

总结:

你的分层结构实现基本正确,符合DDD和整洁架构的原则。主要改进点在于:

  • 完善错误处理机制
  • 考虑增加领域事件
  • 使用DTO进行层间数据传输
  • 添加事务支持

这种结构能够很好地支持你的电子商务项目,随着项目复杂度的增加,可以考虑引入CQRS、事件溯源等模式。

回到顶部