go: Fail-Fast Pattern

项目结构:

Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Fail-Fast Pattern 快速失败模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/6/30 21:25
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : fail_fast.go
*/
package exceptions
 
type ResourceCheckFailedError struct {
    Msg string
}
 
func (e *ResourceCheckFailedError) Error() string {
    return e.Msg
}
 
func NewFailFastErr(msg string) error {
    return &ResourceCheckFailedError{Msg: msg}
}
 
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Fail-Fast Pattern 快速失败模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/6/30 21:26
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : inventory_repo.go
*/
package repository
 
type InventoryRepository struct {
    stockMap map[string]int
}
 
func NewInventoryRepository() *InventoryRepository {
    repo := &InventoryRepository{
        stockMap: make(map[string]int),
    }
    // 初始化测试库存
    repo.stockMap["DIA001"] = 2
    repo.stockMap["DIA002"] = 0
    return repo
}
 
func (r *InventoryRepository) GetStock(productId string) int {
    val, ok := r.stockMap[productId]
    if !ok {
        return -1
    }
    return val
}
 
func (r *InventoryRepository) DeductStock(productId string, qty int) {
    r.stockMap[productId] -= qty
}
 
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Fail-Fast Pattern 快速失败模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/6/30 21:27
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : external_services_repo.go
*/
package repository
 
type ExternalServices struct {
    InventoryService  bool
    PaymentGateway    bool
    QualityInspection bool
    InvoiceService    bool
}
 
func NewExternalServices() *ExternalServices {
    return &ExternalServices{
        InventoryService:  true,
        PaymentGateway:    true,
        QualityInspection: true,
        InvoiceService:    true,
    }
}
 
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Fail-Fast Pattern 快速失败模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/6/30 21:27
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : validation_service.go
*/
package service
 
import (
    "godesginpattern/failfast/exceptions"
    "godesginpattern/failfast/repository"
)
 
type ValidationService struct {
    invRepo *repository.InventoryRepository
    extSvc  *repository.ExternalServices
}
 
func NewValidationService(inv *repository.InventoryRepository, ext *repository.ExternalServices) *ValidationService {
    return &ValidationService{
        invRepo: inv,
        extSvc:  ext,
    }
}
 
func (v *ValidationService) FailFastCheck(customerId, productId string, quantity int) error {
    // 1. 顾客校验
    if len(customerId) < 3 {
        return exceptions.NewFailFastErr("顾客信息无效,立即失败")
    }
    // 2. 商品是否存在
    stock := v.invRepo.GetStock(productId)
    if stock == -1 {
        return exceptions.NewFailFastErr("商品不存在,立即失败")
    }
    // 3. 库存校验
    if stock < quantity {
        return exceptions.NewFailFastErr("库存不足,立即失败")
    }
    // 4. 外部服务校验
    if !v.extSvc.InventoryService {
        return exceptions.NewFailFastErr("库存服务不可用,立即失败")
    }
    if !v.extSvc.PaymentGateway {
        return exceptions.NewFailFastErr("支付网关不可用,立即失败")
    }
    if !v.extSvc.QualityInspection {
        return exceptions.NewFailFastErr("质检服务不可用,立即失败")
    }
    if !v.extSvc.InvoiceService {
        return exceptions.NewFailFastErr("发票服务不可用,立即失败")
    }
    return nil
}
 
 
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Fail-Fast Pattern 快速失败模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/6/30 21:28
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : order_service.go
*/
package service
 
import (
    "godesginpattern/failfast/repository"
    //"godesginpattern/failfast/exceptions"
    "strconv"
    "time"
)
 
type OrderService struct {
    valSvc  *ValidationService
    invRepo *repository.InventoryRepository
    extSvc  *repository.ExternalServices
}
 
func NewOrderService(val *ValidationService, inv *repository.InventoryRepository, ext *repository.ExternalServices) *OrderService {
    return &OrderService{
        valSvc:  val,
        invRepo: inv,
        extSvc:  ext,
    }
}
 
func (o *OrderService) CreateOrder(customerId, productId string, quantity int) (map[string]interface{}, error) {
    err := o.valSvc.FailFastCheck(customerId, productId, quantity)
    if err != nil {
        return nil, err
    }
    // 校验通过执行业务
    o.invRepo.DeductStock(productId, quantity)
    orderId := "ORD" + strconv.FormatInt(time.Now().Unix(), 10)
    res := map[string]interface{}{
        "order_id":        orderId,
        "product_id":      productId,
        "quantity":        quantity,
        "remaining_stock": o.invRepo.GetStock(productId),
        "status":          "success",
    }
    return res, nil
}
 
 
 
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Fail-Fast Pattern 快速失败模式
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/6/30 21:31
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : order_controller.go
*/
package api
 
import (
    "fmt"
    "godesginpattern/failfast/exceptions"
    "godesginpattern/failfast/service"
)
 
type OrderController struct {
    orderSvc *service.OrderService
}
 
func NewOrderController(svc *service.OrderService) *OrderController {
    return &OrderController{
        orderSvc: svc,
    }
}
 
func (c *OrderController) CreateJewelryOrder(customerId, productId string, quantity int) string {
    res, err := c.orderSvc.CreateOrder(customerId, productId, quantity)
    if err != nil {
        if e, ok := err.(*exceptions.ResourceCheckFailedError); ok {
            return "\n❌ 快速失败: " + e.Msg
        }
        return "\n❌ 业务异常: " + err.Error()
    }
    return "\n✅ 订单创建成功!详情:" + fmt.Sprintf("%v", res)
}

调用:

Go 复制代码
/*
# 版权所有  2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:failfast
# Author    : geovindu,Geovin Du 涂聚文.
# IDE       : goLang 2024.3.6 go 26.2
# os        : windows 10
# database  : mysql 9.0 sql server 2019, postgreSQL 17.0  Oracle 21c Neo4j
# Datetime  : 2026/6/30 21:32
# User      :  geovindu
# Product   : GoLand
# Project   : godesginpattern
# File      : failfastbll.go
*/
package bll
 
import (
    "fmt"
    "godesginpattern/failfast/api"
    "godesginpattern/failfast/repository"
    "godesginpattern/failfast/service"
)
 
func FailfastMain() {
    // 初始化依赖(和Python代码一一对应)
    inventoryRepo := repository.NewInventoryRepository()
    extServices := repository.NewExternalServices()
    validationService := service.NewValidationService(inventoryRepo, extServices)
    orderService := service.NewOrderService(validationService, inventoryRepo, extServices)
    controller := api.NewOrderController(orderService)
 
    // ======================
    // 测试场景 完全对齐Python输出
    // ======================
    fmt.Println("==== 场景1:正常下单 ===")
    fmt.Println(controller.CreateJewelryOrder("C1001", "DIA001", 1))
 
    fmt.Println("\n==== 场景2:库存不足 ===")
    fmt.Println(controller.CreateJewelryOrder("C1001", "DIA002", 1))
 
    fmt.Println("\n==== 场景3:顾客无效 ===")
    fmt.Println(controller.CreateJewelryOrder("C", "DIA001", 1))
 
    fmt.Println("\n==== 场景4:支付服务挂了 ===")
    extServices.PaymentGateway = false
    fmt.Println(controller.CreateJewelryOrder("C1001", "DIA001", 1))
}
  

输出: