项目结构:

Go
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Pipeline 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/21 14:07
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : config.go
*/
package config
import (
"log"
"os"
"time"
)
const (
Timeout = 1 * time.Second
RetryTimes = 2
MaxReworkCount = 2
ProcessSleep = 200 * time.Millisecond
)
var Logger = log.New(os.Stdout, "", log.Ldate|log.Ltime|log.Lmsgprefix)
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Pipeline 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/21 14:08
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : model.go
*/
package model
type RawStone struct {
SN int
Carat float64
Origin string
}
type CutDiamond struct {
SN int
Carat float64
CutGrade string
ReworkCount int
}
type ClarityResult struct {
SN int
Grade string
Pass bool
Diamond *CutDiamond
}
type ColorResult struct {
SN int
Grade string
Pass bool
Diamond *CutDiamond
}
type QCMerged struct {
SN int
Carat float64
Cut string
Clarity string
Color string
PassAll bool
Diamond *CutDiamond
}
type Inlaid struct {
SN int
Metal string
QC *QCMerged
LaborCost float64
}
type Finished struct {
SN int
Name string
Price float64
}
type SaleOrder struct {
SN int
Name string
Price float64
}
type DefectItem struct {
Item any
Stage string
Err string
}
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Pipeline 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/21 14:09
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : channel.go
*/
package core
import "sync"
const StopSignal = "__STOP__"
type Channel[T any] struct {
ch chan T
}
func NewChannel[T any]() *Channel[T] {
return &Channel[T]{ch: make(chan T, 10)}
}
func (c *Channel[T]) Send(item T) {
c.ch <- item
}
func (c *Channel[T]) Recv() (T, bool) {
v, ok := <-c.ch
return v, ok
}
func (c *Channel[T]) Close() {
close(c.ch)
}
func SplitStream[T any](src *Channel[T], dsts []*Channel[T], wg *sync.WaitGroup) {
defer wg.Done()
for {
item, ok := src.Recv()
if !ok {
for _, d := range dsts {
d.Close()
}
return
}
for _, d := range dsts {
d.Send(item)
}
}
}
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Pipeline 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/21 16:39
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : metrics.go
*/
package core
import "sync"
type Metrics struct {
Total int
Success int
Fail int
Retry int
}
var (
stageMetrics = make(map[string]*Metrics)
mu sync.RWMutex
)
func InitStage(name string) {
mu.Lock()
defer mu.Unlock()
if stageMetrics[name] == nil {
stageMetrics[name] = &Metrics{}
}
}
func IncTotal(name string) {
mu.Lock()
defer mu.Unlock()
stageMetrics[name].Total++
}
func IncSuccess(name string) {
mu.Lock()
defer mu.Unlock()
stageMetrics[name].Success++
}
func IncFail(name string) {
mu.Lock()
defer mu.Unlock()
stageMetrics[name].Fail++
}
func IncRetry(name string) {
mu.Lock()
defer mu.Unlock()
stageMetrics[name].Retry++
}
func GetMetrics() map[string]*Metrics {
mu.RLock()
defer mu.RUnlock()
copy := make(map[string]*Metrics)
for k, v := range stageMetrics {
copy[k] = v
}
return copy
}
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Pipeline 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/21 16:40
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : stage.go
*/
package core
import (
"godesginpattern/pipeline/config"
"godesginpattern/pipeline/model"
"time"
)
func RunStage[Tin, Tout any](
name string,
in *Channel[Tin],
out *Channel[Tout],
defect *Channel[*model.DefectItem],
process func(Tin) (Tout, error),
) {
config.Logger.Printf("【阶段启动】%s", name)
InitStage(name)
for {
item, ok := in.Recv()
if !ok {
break
}
IncTotal(name)
var res Tout
var err error
success := false
for attempt := 0; attempt <= config.RetryTimes; attempt++ {
res, err = process(item)
if err == nil {
success = true
break
}
IncRetry(name)
sn := getSN(item)
config.Logger.Printf("【%s】SN:%d 第%d次失败: %v", name, sn, attempt+1, err)
time.Sleep(100 * time.Millisecond)
}
if success {
IncSuccess(name)
out.Send(res)
} else {
IncFail(name)
defect.Send(&model.DefectItem{
Item: item,
Stage: name,
Err: err.Error(),
})
}
}
out.Close()
config.Logger.Printf("【阶段结束】%s", name)
}
func getSN(v any) int {
switch t := v.(type) {
case *model.CutDiamond:
return t.SN
case *model.QCMerged:
return t.SN
case *model.Inlaid:
return t.SN
case *model.Finished:
return t.SN
default:
return 0
}
}
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Pipeline 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/21 16:42
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : fork_join.go
*/
package core
import (
"godesginpattern/pipeline/model"
"sync"
)
func ForkBranch[Tin, Tout any](
in *Channel[Tin],
out *Channel[Tout],
fn func(Tin) Tout,
wg *sync.WaitGroup,
) {
defer wg.Done()
for {
item, ok := in.Recv()
if !ok {
break
}
out.Send(fn(item))
}
out.Close()
}
func JoinMerger(
clarityCh *Channel[*model.ClarityResult],
colorCh *Channel[*model.ColorResult],
out *Channel[*model.QCMerged],
merge func(*model.CutDiamond, *model.ClarityResult, *model.ColorResult) *model.QCMerged,
) {
clarityMap := make(map[int]*model.ClarityResult)
colorMap := make(map[int]*model.ColorResult)
var wg sync.WaitGroup
wg.Add(2)
go func() {
defer wg.Done()
for {
r, ok := clarityCh.Recv()
if !ok {
break
}
clarityMap[r.SN] = r
}
}()
go func() {
defer wg.Done()
for {
r, ok := colorCh.Recv()
if !ok {
break
}
colorMap[r.SN] = r
}
}()
wg.Wait()
for sn, cr := range clarityMap {
if cc, ok := colorMap[sn]; ok {
out.Send(merge(cr.Diamond, cr, cc))
}
}
out.Close()
}
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Pipeline 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/21 16:43
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : defect.go
*/
package core
import (
"godesginpattern/pipeline/config"
"godesginpattern/pipeline/model"
)
func DefectReworkConsumer(
defectCh *Channel[*model.DefectItem],
reworkCh *Channel[*model.CutDiamond],
) {
config.Logger.Println("次品返工分拣中心启动")
for {
item, ok := defectCh.Recv()
if !ok {
break
}
diamond, ok := item.Item.(*model.CutDiamond)
if !ok {
continue
}
if diamond.ReworkCount < config.MaxReworkCount {
diamond.ReworkCount++
config.Logger.Printf("【返工】SN:%d 第%d次回流切割工序", diamond.SN, diamond.ReworkCount)
reworkCh.Send(diamond)
} else {
config.Logger.Printf("【报废】SN:%d 超过最大返工次数", diamond.SN)
}
}
reworkCh.Close()
}
Go
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Pipeline 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/21 16:45
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : services.go
*/
package service
import (
"errors"
"godesginpattern/pipeline/config"
"godesginpattern/pipeline/model"
"math/rand"
"strconv"
"time"
)
func CutStone(raw *model.RawStone) (*model.CutDiamond, error) {
time.Sleep(config.ProcessSleep)
grade := "VG"
if raw.Carat >= 1.0 {
grade = "EX"
}
return &model.CutDiamond{
SN: raw.SN,
Carat: raw.Carat,
CutGrade: grade,
}, nil
}
func CheckClarity(d *model.CutDiamond) *model.ClarityResult {
time.Sleep(config.ProcessSleep)
grades := []string{"VS1", "VS2", "SI1"}
g := grades[rand.Intn(len(grades))]
pass := g != "SI1" || d.Carat > 0.7
return &model.ClarityResult{
SN: d.SN,
Grade: g,
Pass: pass,
Diamond: d,
}
}
func CheckColor(d *model.CutDiamond) *model.ColorResult {
time.Sleep(config.ProcessSleep)
grades := []string{"D", "G", "J"}
g := grades[rand.Intn(len(grades))]
pass := g == "D" || g == "G"
return &model.ColorResult{
SN: d.SN,
Grade: g,
Pass: pass,
Diamond: d,
}
}
func MergeQC(d *model.CutDiamond, c *model.ClarityResult, co *model.ColorResult) *model.QCMerged {
return &model.QCMerged{
SN: d.SN,
Carat: d.Carat,
Cut: d.CutGrade,
Clarity: c.Grade,
Color: co.Grade,
PassAll: c.Pass && co.Pass,
Diamond: d,
}
}
func Inlay(qc *model.QCMerged) (*model.Inlaid, error) {
time.Sleep(config.ProcessSleep)
if !qc.PassAll {
return nil, errors.New("钻石质检未通过,禁止镶嵌加工")
}
metals := []string{"18K黄金", "PT950铂金", "S925银"}
metal := metals[rand.Intn(len(metals))]
return &model.Inlaid{
SN: qc.SN,
Metal: metal,
QC: qc,
LaborCost: qc.Carat * 1200,
}, nil
}
func Finish(in *model.Inlaid) (*model.Finished, error) {
time.Sleep(config.ProcessSleep)
cost := in.LaborCost + in.QC.Carat*8500
price := cost * 1.75
name := in.Metal + "钻戒-" + strconv.Itoa(in.SN)
return &model.Finished{
SN: in.SN,
Name: name,
Price: price,
}, nil
}
func Sale(f *model.Finished) (*model.SaleOrder, error) {
time.Sleep(config.ProcessSleep / 2)
return &model.SaleOrder{
SN: f.SN,
Name: f.Name,
Price: f.Price,
}, nil
}
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Pipeline 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/21 16:45
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : factory.go
*/
package factory
import (
"godesginpattern/pipeline/core"
"godesginpattern/pipeline/model"
"godesginpattern/pipeline/service"
"sync"
)
func BuildPipeline(
source *core.Channel[*model.RawStone], // 修复:输入改为 RawStone
) (*core.Channel[*model.SaleOrder], *sync.WaitGroup) {
// 所有通道类型对齐
rawIn := source
cutOut := core.NewChannel[*model.CutDiamond]()
clarityIn := core.NewChannel[*model.CutDiamond]()
colorIn := core.NewChannel[*model.CutDiamond]()
clarityOut := core.NewChannel[*model.ClarityResult]()
colorOut := core.NewChannel[*model.ColorResult]()
mergedOut := core.NewChannel[*model.QCMerged]()
inlayOut := core.NewChannel[*model.Inlaid]()
finishOut := core.NewChannel[*model.Finished]()
saleOut := core.NewChannel[*model.SaleOrder]()
defectCh := core.NewChannel[*model.DefectItem]()
var wg sync.WaitGroup
wg.Add(3)
// 分流器:切割完成 → 分发给净度/颜色检测
go core.SplitStream(cutOut, []*core.Channel[*model.CutDiamond]{clarityIn, colorIn}, &wg)
// 并行质检分支
go core.ForkBranch(clarityIn, clarityOut, service.CheckClarity, &wg)
go core.ForkBranch(colorIn, colorOut, service.CheckColor, &wg)
// 合并两路质检结果
go core.JoinMerger(clarityOut, colorOut, mergedOut, service.MergeQC)
// 流水线所有工序(类型 100% 匹配)
go core.RunStage("1-原石切割", rawIn, cutOut, defectCh, service.CutStone)
go core.RunStage("2-贵金属镶嵌", mergedOut, inlayOut, defectCh, service.Inlay)
go core.RunStage("3-成品定价", inlayOut, finishOut, defectCh, service.Finish)
go core.RunStage("4-销售出库", finishOut, saleOut, defectCh, service.Sale)
// 次品返工
go core.DefectReworkConsumer(defectCh, cutOut)
return saleOut, &wg
}
调用:
Go
/*
# 版权所有 2026 ©涂聚文有限公司™ ®
# 许可信息查看:言語成了邀功盡責的功臣,還需要行爲每日來值班嗎
# 描述:Pipeline 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/21 16:47
# User : geovindu
# Product : GoLand
# Project : godesginpattern
# File : pipelinebll.go
*/
package bll
import (
"godesginpattern/pipeline/config"
"godesginpattern/pipeline/core"
"godesginpattern/pipeline/factory"
"godesginpattern/pipeline/model"
)
func PipelineMain() {
config.Logger.Println("===== 企业级珠宝异步Pipeline启动(并行质检+次品返工)=====")
// 输入通道:RawStone 原石(完全对齐)
source := core.NewChannel[*model.RawStone]()
raws := []*model.RawStone{
{SN: 2001, Carat: 0.62, Origin: "南非"},
{SN: 2002, Carat: 1.15, Origin: "博茨瓦纳"},
{SN: 2003, Carat: 0.48, Origin: "俄罗斯"},
{SN: 2004, Carat: 1.32, Origin: "南非"},
{SN: 2005, Carat: 0.75, Origin: "澳大利亚"},
{SN: 2007, Carat: 0.90, Origin: "纳米比亚"},
}
// 直接投放原石,不再提前切割
for _, r := range raws {
config.Logger.Printf("原料进料 SN:%d", r.SN)
source.Send(r)
}
source.Close()
// 启动流水线
saleOut, wg := factory.BuildPipeline(source)
// 消费销售结果
count := 0
for {
order, ok := saleOut.Recv()
if !ok {
break
}
count++
config.Logger.Printf("✅ 销售单据 SN:%d 售价:%.2f", order.SN, order.Price)
}
wg.Wait()
config.Logger.Println("\n========== 流水线执行完成 ==========")
config.Logger.Printf("总投入原石:%d件 成功销售:%d件", len(raws), count)
}
输出:
