设计模式是对在特定情境下,反复出现的问题提供一套成熟的、可复用的解决方案。Go 语言以其简洁、并发优先的特性,在实现设计模式时通常会有其独特的“Go 惯例”,有时会与传统面向对象设计模式的实现有所不同。本篇将探讨 Go 语言中常用的设计模式,并结合 Go 的特性给出实现示例。

核心思想:Go 语言的设计模式实现通常倾向于简洁、组合而非继承、接口优先以及利用 Goroutine 和 Channel 进行并发处理。


一、Go 语言与设计模式的哲学

Go 语言在设计模式的实践上,有一些与传统 OOP 语言不同的哲学:

  1. 组合优于继承:Go 没有类继承的概念,而是通过结构体嵌入(Composition)和接口(Interfaces)来实现代码复用和多态。
  2. 接口优先:Go 的接口是隐式实现的(implicit interface satisfaction),任何类型只要实现了接口定义的所有方法,就自然地实现了该接口。这使得接口更加灵活,鼓励“小接口,大组合”的原则。
  3. 并发原语:Goroutine 和 Channel 是 Go 语言的核心并发原语,许多设计模式在 Go 中会自然融入并发考量。
  4. 简洁性:Go 鼓励编写简洁、直接的代码,有时为了追求简洁会避免过度设计,一些复杂的设计模式可能会被更简单的 Go 风格代码所替代。

二、创建型设计模式 (Creational Design Patterns)

创建型模式关注对象的创建机制,旨在以一种安全、灵活的方式创建对象。

2.1 单例模式 (Singleton Pattern)

确保一个类只有一个实例,并提供一个全局访问点。在 Go 中,通常使用 sync.Once 来保证线程安全的单例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package singleton

import (
"fmt"
"sync"
)

type singleton struct {
name string
}

var (
instance *singleton
once sync.Once
)

// GetInstance 返回单例实例
func GetInstance() *singleton {
once.Do(func() {
instance = &singleton{name: "Singleton Instance"}
fmt.Println("Singleton instance created.")
})
return instance
}

// DoSomething 模拟单例实例的方法
func (s *singleton) DoSomething() {
fmt.Printf("Doing something with %s\n", s.name)
}

/*
// Usage:
func main() {
s1 := singleton.GetInstance()
s1.DoSomething()

s2 := singleton.GetInstance()
s2.DoSomething()

if s1 == s2 {
fmt.Println("s1 and s2 are the same instance.")
}
}
*/

2.2 工厂模式 (Factory Pattern)

定义一个创建对象的接口,但由子类决定实例化哪个类。在 Go 中,通常使用一个函数返回接口类型,根据输入参数创建不同具体的结构体实例。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package factory

import "fmt"

// Product 是产品接口
type Product interface {
Use()
}

// ConcreteProductA 是具体产品A
type ConcreteProductA struct{}

func (p *ConcreteProductA) Use() {
fmt.Println("Using ConcreteProductA")
}

// ConcreteProductB 是具体产品B
type ConcreteProductB struct{}

func (p *ConcreteProductB) Use() {
fmt.Println("Using ConcreteProductB")
}

// Factory 是工厂函数
func Factory(productType string) Product {
switch productType {
case "A":
return &ConcreteProductA{}
case "B":
return &ConcreteProductB{}
default:
return nil
}
}

/*
// Usage:
func main() {
productA := factory.Factory("A")
if productA != nil {
productA.Use()
}

productB := factory.Factory("B")
if productB != nil {
productB.Use()
}

productC := factory.Factory("C")
if productC == nil {
fmt.Println("Product C not found.")
}
}
*/

2.3 抽象工厂模式 (Abstract Factory Pattern)

提供一个接口,用于创建一系列相关或相互依赖的对象,而无需指定它们具体的类。在 Go 中,这通常通过定义多个工厂函数或返回不同类型工厂的工厂来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package abstract_factory

import "fmt"

// ProductA, ProductB ... 是产品族的接口
type ProductA interface {
MethodA()
}

type ProductB interface {
MethodB()
}

// === 产品族1 ===
type ConcreteProductA1 struct{}
func (p *ConcreteProductA1) MethodA() { fmt.Println("ProductA1 MethodA") }

type ConcreteProductB1 struct{}
func (p *ConcreteProductB1) MethodB() { fmt.Println("ProductB1 MethodB") }

// Factory1 是具体工厂1
type Factory1 struct{}
func (f *Factory1) CreateProductA() ProductA { return &ConcreteProductA1{} }
func (f *Factory1) CreateProductB() ProductB { return &ConcreteProductB1{} }

// === 产品族2 ===
type ConcreteProductA2 struct{}
func (p *ConcreteProductA2) MethodA() { fmt.Println("ProductA2 MethodA") }

type ConcreteProductB2 struct{}
func (p *ConcreteProductB2) MethodB() { fmt.Println("ProductB2 MethodB") }

// Factory2 是具体工厂2
type Factory2 struct{}
func (f *Factory2) CreateProductA() ProductA { return &ConcreteProductA2{} }
func (f *Factory2) CreateProductB() ProductB { return &ConcreteProductB2{} }

// AbstractFactory 是抽象工厂接口
type AbstractFactory interface {
CreateProductA() ProductA
CreateProductB() ProductB
}

/*
// Usage:
func main() {
var factory AbstractFactory

// 使用工厂1
factory = &abstract_factory.Factory1{}
pa1 := factory.CreateProductA()
pb1 := factory.CreateProductB()
pa1.MethodA()
pb1.MethodB()

// 使用工厂2
factory = &abstract_factory.Factory2{}
pa2 := factory.CreateProductA()
pb2 := factory.CreateProductB()
pa2.MethodA()
pb2.MethodB()
}
*/

2.4 建造者模式 (Builder Pattern)

将一个复杂对象的构建与其表示分离,使得同样的构建过程可以创建不同的表示。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
package builder

import "fmt"

// Product 是最终要构建的复杂对象
type Product struct {
PartA string
PartB string
PartC string
}

func (p *Product) Show() {
fmt.Printf("Product: PartA=%s, PartB=%s, PartC=%s\n", p.PartA, p.PartB, p.PartC)
}

// Builder 是抽象建造者接口
type Builder interface {
BuildPartA()
BuildPartB()
BuildPartC()
GetProduct() *Product
}

// ConcreteBuilder 是具体建造者
type ConcreteBuilder struct {
product *Product
}

func NewConcreteBuilder() *ConcreteBuilder {
return &ConcreteBuilder{product: &Product{}}
}

func (b *ConcreteBuilder) BuildPartA() {
b.product.PartA = "PartA constructed"
}

func (b *ConcreteBuilder) BuildPartB() {
b.product.PartB = "PartB constructed"
}

func (b *ConcreteBuilder) BuildPartC() {
b.product.PartC = "PartC constructed"
}

func (b *ConcreteBuilder) GetProduct() *Product {
return b.product
}

// Director 是指导者,负责按照特定顺序构建Product
type Director struct {
builder Builder
}

func NewDirector(builder Builder) *Director {
return &Director{builder: builder}
}

func (d *Director) Construct() *Product {
d.builder.BuildPartA()
d.builder.BuildPartB()
d.builder.BuildPartC()
return d.builder.GetProduct()
}

/*
// Usage:
func main() {
builder := builder.NewConcreteBuilder()
director := builder.NewDirector(builder)
product := director.Construct()
product.Show()
}
*/

三、结构型设计模式 (Structural Design Patterns)

结构型模式关注如何将类和对象组合成更大的结构,以实现新的功能。

3.1 适配器模式 (Adapter Pattern)

将一个类的接口转换成客户希望的另一个接口。适配器模式使原本由于接口不兼容而不能一起工作的那些类可以一起工作。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
package adapter

import "fmt"

// Target 是客户端期望的接口
type Target interface {
Request() string
}

// Adaptee 是需要被适配的接口(不兼容的接口)
type Adaptee struct{}

func (s *Adaptee) SpecificRequest() string {
return "Specific request from Adaptee"
}

// Adapter 是适配器,实现了 Target 接口,并包含 Adaptee 实例
type Adapter struct {
adaptee *Adaptee
}

func NewAdapter(adaptee *Adaptee) *Adapter {
return &Adapter{adaptee: adaptee}
}

func (a *Adapter) Request() string {
return "Adapter translated: " + a.adaptee.SpecificRequest()
}

/*
// Usage:
func main() {
adaptee := &adapter.Adaptee{}
target := adapter.NewAdapter(adaptee)
fmt.Println(target.Request())
}
*/

3.2 装饰器模式 (Decorator Pattern)

动态地给一个对象添加一些额外的职责。相比于使用继承,装饰器模式更加灵活。在 Go 中,通常通过结构体嵌入和接口来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
package decorator

import "fmt"

// Component 是被装饰的接口
type Component interface {
Operation() string
}

// ConcreteComponent 是具体组件
type ConcreteComponent struct{}

func (c *ConcreteComponent) Operation() string {
return "ConcreteComponent"
}

// Decorator 是抽象装饰器 - Go中通常直接定义具体的装饰器
// 或者一个结构体嵌入Component接口
type BaseDecorator struct {
component Component
}

func (d *BaseDecorator) Operation() string {
return d.component.Operation()
}

// ConcreteDecoratorA 是具体装饰器A
type ConcreteDecoratorA struct {
BaseDecorator
}

func NewConcreteDecoratorA(c Component) *ConcreteDecoratorA {
return &ConcreteDecoratorA{BaseDecorator{component: c}}
}

func (d *ConcreteDecoratorA) Operation() string {
return "DecoratorA(" + d.BaseDecorator.Operation() + ")"
}

// ConcreteDecoratorB 是具体装饰器B
type ConcreteDecoratorB struct {
BaseDecorator
}

func NewConcreteDecoratorB(c Component) *ConcreteDecoratorB {
return &ConcreteDecoratorB{BaseDecorator{component: c}}
}

func (d *ConcreteDecoratorB) Operation() string {
return "DecoratorB(" + d.BaseDecorator.Operation() + ")"
}

/*
// Usage:
func main() {
component := &decorator.ConcreteComponent{}
fmt.Println(component.Operation()) // 输出: ConcreteComponent

decoratorA := decorator.NewConcreteDecoratorA(component)
fmt.Println(decoratorA.Operation()) // 输出: DecoratorA(ConcreteComponent)

decoratorB := decorator.NewConcreteDecoratorB(decoratorA) // 装饰器可以层层嵌套
fmt.Println(decoratorB.Operation()) // 输出: DecoratorB(DecoratorA(ConcreteComponent))
}
*/

3.3 代理模式 (Proxy Pattern)

为另一个对象提供一个替身或占位符,以控制对这个对象的访问。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
package proxy

import "fmt"

// Subject 是主题接口
type Subject interface {
Request() string
}

// RealSubject 是真实主题
type RealSubject struct{}

func (s *RealSubject) Request() string {
return "RealSubject handling request"
}

// Proxy 是代理
type Proxy struct {
realSubject *RealSubject // 持有真实主题的引用
}

func NewProxy() *Proxy {
return &Proxy{}
}

func (p *Proxy) Request() string {
// 在访问真实主题之前/之后可以执行一些额外操作
fmt.Println("Proxy: Doing something before forwarding request.")
if p.realSubject == nil {
p.realSubject = &RealSubject{} // 延迟初始化真实主题
}
result := p.realSubject.Request()
fmt.Println("Proxy: Doing something after forwarding request.")
return result
}

/*
// Usage:
func main() {
proxy := proxy.NewProxy()
fmt.Println(proxy.Request())
}
*/

3.4 外观模式 (Facade Pattern)

为子系统中的一组接口提供一个统一的接口。外观定义了一个高层接口,这个接口使得子系统更容易使用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
package facade

import "fmt"

// SubsystemA, SubsystemB, SubsystemC 是子系统
type SubsystemA struct{}
func (s *SubsystemA) OperationA() string { return "SubsystemA Operation" }

type SubsystemB struct{}
func (s *SubsystemB) OperationB() string { return "SubsystemB Operation" }

type SubsystemC struct{}
func (s *SubsystemC) OperationC() string { return "SubsystemC Operation" }

// Facade 是外观模式的入口
type Facade struct {
subsystemA *SubsystemA
subsystemB *SubsystemB
subsystemC *SubsystemC
}

func NewFacade() *Facade {
return &Facade{
subsystemA: &SubsystemA{},
subsystemB: &SubsystemB{},
subsystemC: &SubsystemC{},
}
}

// OperateMethod1 提供了子系统A和B的组合操作
func (f *Facade) OperateMethod1() string {
result := f.subsystemA.OperationA() + "\n"
result += f.subsystemB.OperationB()
return result
}

// OperateMethod2 提供了子系统C的简单操作
func (f *Facade) OperateMethod2() string {
return f.subsystemC.OperationC()
}

/*
// Usage:
func main() {
facade := facade.NewFacade()
fmt.Println("--- Method 1 ---")
fmt.Println(facade.OperateMethod1())
fmt.Println("\n--- Method 2 ---")
fmt.Println(facade.OperateMethod2())
}
*/

四、行为型设计模式 (Behavioral Design Patterns)

行为型模式关注对象之间的职责分配和通信方式。

4.1 观察者模式 (Observer Pattern)

定义对象间的一种一对多的依赖关系,当一个对象的状态发生改变时,所有依赖于它的对象都得到通知并被自动更新。Go 中通常通过 Channel 或回调函数实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
package observer

import "fmt"

// Observer 是观察者接口
type Observer interface {
Update(message string)
}

// ConcreteObserver 是具体观察者
type ConcreteObserver struct {
id int
}

func NewConcreteObserver(id int) *ConcreteObserver {
return &ConcreteObserver{id: id}
}

func (o *ConcreteObserver) Update(message string) {
fmt.Printf("Observer %d received message: %s\n", o.id, message)
}

// Subject 是主题 (被观察者)
type Subject struct {
observers []Observer
}

func (s *Subject) Attach(o Observer) {
s.observers = append(s.observers, o)
}

func (s *Subject) Detach(o Observer) {
for i, obs := range s.observers {
if obs == o {
s.observers = append(s.observers[:i], s.observers[i+1:]...)
return
}
}
}

func (s *Subject) Notify(message string) {
for _, o := range s.observers {
o.Update(message)
}
}

/*
// Usage:
func main() {
subject := &observer.Subject{}

obs1 := observer.NewConcreteObserver(1)
obs2 := observer.NewConcreteObserver(2)

subject.Attach(obs1)
subject.Attach(obs2)

subject.Notify("State changed!")

subject.Detach(obs1)
subject.Notify("Another state change!")
}
*/

Go 风格的观察者模式 也可以利用 Channel:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
package observer_channel

import "fmt"

// Event 是观察者传递的消息类型
type Event struct {
Message string
}

// Observer 是一个接收 Event 的 Channel
type Observer chan Event

// Subject 是主题
type Subject struct {
subscribers []Observer
}

func (s *Subject) Register(obs Observer) {
s.subscribers = append(s.subscribers, obs)
}

func (s *Subject) Unregister(obs Observer) {
for i, o := range s.subscribers {
if o == obs {
close(o) // 关闭 Channel
s.subscribers = append(s.subscribers[:i], s.subscribers[i+1:]...)
return
}
}
}

func (s *Subject) Notify(event Event) {
for _, obs := range s.subscribers {
select {
case obs <- event: // 非阻塞发送
default:
fmt.Println("Observer channel is full, skipping event:", event.Message)
}
}
}

/*
// Usage:
func main() {
subject := &observer_channel.Subject{}

obs1 := make(observer_channel.Observer, 1) // 有缓冲 Channel
obs2 := make(observer_channel.Observer, 1)

subject.Register(obs1)
subject.Register(obs2)

go func() {
for event := range obs1 {
fmt.Printf("Observer 1 received: %s\n", event.Message)
}
fmt.Println("Observer 1 stopped.")
}()

go func() {
for event := range obs2 {
fmt.Printf("Observer 2 received: %s\n", event.Message)
}
fmt.Println("Observer 2 stopped.")
}()

subject.Notify(observer_channel.Event{Message: "First event"})
time.Sleep(100 * time.Millisecond) // 等待 goroutine 处理

subject.Unregister(obs1)
subject.Notify(observer_channel.Event{Message: "Second event, obs1 removed"})
time.Sleep(100 * time.Millisecond)

// 模拟阻塞情况
subject.Notify(observer_channel.Event{Message: "Third event (will block if channel is full)"})
subject.Notify(observer_channel.Event{Message: "Fourth event (will be skipped)"}) // 如果没人读取,这个会被跳过
time.Sleep(1 * time.Second) // 确保所有 goroutines 有时间完成
}
*/

4.2 策略模式 (Strategy Pattern)

定义一系列算法,并将每个算法封装起来,使它们可以相互替换。策略模式让算法的变化独立于使用算法的客户。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package strategy

import "fmt"

// Strategy 是策略接口
type Strategy interface {
Execute(a, b int) int
}

// ConcreteStrategyAdd 是具体策略:加法
type ConcreteStrategyAdd struct{}

func (s *ConcreteStrategyAdd) Execute(a, b int) int {
return a + b
}

// ConcreteStrategySubtract 是具体策略:减法
type ConcreteStrategySubtract struct{}

func (s *ConcreteStrategySubtract) Execute(a, b int) int {
return a - b
}

// Context 是上下文,持有策略对象
type Context struct {
strategy Strategy
}

func NewContext(strategy Strategy) *Context {
return &Context{strategy: strategy}
}

func (c *Context) SetStrategy(strategy Strategy) {
c.strategy = strategy
}

func (c *Context) PerformOperation(a, b int) int {
return c.strategy.Execute(a, b)
}

/*
// Usage:
func main() {
// 使用加法策略
context := strategy.NewContext(&strategy.ConcreteStrategyAdd{})
result := context.PerformOperation(10, 5)
fmt.Printf("10 + 5 = %d\n", result) // Output: 10 + 5 = 15

// 切换到减法策略
context.SetStrategy(&strategy.ConcreteStrategySubtract{})
result = context.PerformOperation(10, 5)
fmt.Printf("10 - 5 = %d\n", result) // Output: 10 - 5 = 5
}
*/

4.3 模板方法模式 (Template Method Pattern)

定义一个算法的骨架,将一些步骤延迟到子类中。模板方法使得子类可以在不改变算法结构的情况下重新定义算法的某些特定步骤。在 Go 中,通常通过接口和结构体嵌入结合实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
package template_method

import "fmt"

// AbstractClass 是抽象类 (Go 中通过接口定义骨架,通过结构体嵌入实现公共行为)
type AbstractClass interface {
TemplateMethod()
step1() // 抽象步骤1
step2() // 抽象步骤2
hook() // 钩子方法 (可选)
}

// Template 实现公共的TemplateMethod,并依赖具体的step1和step2
// 它嵌入了 AbstractClass 接口,但更常见的是一个基结构体,包含对自身的接口引用
type template struct {
impl AbstractClass // 保存具体实现的引用
}

func (t *template) TemplateMethod() {
fmt.Println("Starting Template Method...")
t.impl.step1()
t.impl.step2()
t.impl.hook() // 可选钩子
fmt.Println("Template Method Finished.")
}

// ConcreteClassA 是具体实现A
type ConcreteClassA struct {
template // 嵌入模板结构体
}

func NewConcreteClassA() *ConcreteClassA {
c := &ConcreteClassA{}
c.template.impl = c // 将自身作为实现传递给模板
return c
}

func (c *ConcreteClassA) step1() {
fmt.Println("ConcreteClassA: Step 1 executed.")
}

func (c *ConcreteClassA) step2() {
fmt.Println("ConcreteClassA: Step 2 executed.")
}

func (c *ConcreteClassA) hook() {
fmt.Println("ConcreteClassA: Hook executed.")
}

// ConcreteClassB 是具体实现B
type ConcreteClassB struct {
template
}

func NewConcreteClassB() *ConcreteClassB {
c := &ConcreteClassB{}
c.template.impl = c
return c
}

func (c *ConcreteClassB) step1() {
fmt.Println("ConcreteClassB: Step 1 executed differently.")
}

func (c *ConcreteClassB) step2() {
fmt.Println("ConcreteClassB: Step 2 executed differently.")
}

func (c *ConcreteClassB) hook() {
// ConcreteClassB choose not to implement the hook or do nothing
fmt.Println("ConcreteClassB: Hook is optional.")
}

/*
// Usage:
func main() {
fmt.Println("--- Using ConcreteClassA ---")
classA := template_method.NewConcreteClassA()
classA.TemplateMethod()

fmt.Println("\n--- Using ConcreteClassB ---")
classB := template_method.NewConcreteClassB()
classB.TemplateMethod()
}
*/

4.4 迭代器模式 (Iterator Pattern)

提供一种顺序访问聚合对象中各个元素的方法,而不暴露该对象的内部表示。Go 语言中,数组、切片、映射等有内置的 for...range 机制,通常无需手动实现迭代器。但在某些复杂数据结构 (如树、图) 中,自定义迭代器仍然有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
package iterator

import "fmt"

// Item 是聚合中的元素
type Item struct {
Name string
}

// Aggregate 是聚合接口
type Aggregate interface {
Iterator() Iterator
}

// Iterator 是迭代器接口
type Iterator interface {
HasNext() bool
Next() *Item
}

// ConcreteAggregate 是具体聚合
type ConcreteAggregate struct {
items []*Item
}

func (a *ConcreteAggregate) AddItem(item *Item) {
a.items = append(a.items, item)
}

func (a *ConcreteAggregate) Iterator() Iterator {
return &ConcreteIterator{
aggregate: a,
index: 0,
}
}

// ConcreteIterator 是具体迭代器
type ConcreteIterator struct {
aggregate *ConcreteAggregate
index int
}

func (it *ConcreteIterator) HasNext() bool {
return it.index < len(it.aggregate.items)
}

func (it *ConcreteIterator) Next() *Item {
if it.HasNext() {
item := it.aggregate.items[it.index]
it.index++
return item
}
return nil
}

/*
// Usage:
func main() {
aggregate := &iterator.ConcreteAggregate{}
aggregate.AddItem(&iterator.Item{Name: "Item 1"})
aggregate.AddItem(&iterator.Item{Name: "Item 2"})
aggregate.AddItem(&iterator.Item{Name: "Item 3"})

it := aggregate.Iterator()
for it.HasNext() {
item := it.Next()
fmt.Printf("Processing item: %s\n", item.Name)
}
}
*/

五、Go 语言特有模式 / 惯用法

除了经典的 GoF 设计模式,Go 语言因其独特的特性,也催生了一些独有的惯用模式。

5.1 Goroutine / Channel 模式

这是 Go 语言最核心的并发模式,广泛应用于各种并发场景。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
package goroutine_channel

import (
"fmt"
"sync"
"time"
)

// Worker 是一个执行任务的 goroutine
func Worker(id int, tasks <-chan int, results chan<- string) {
for task := range tasks {
fmt.Printf("Worker %d started task %d\n", id, task)
time.Sleep(time.Duration(task) * 100 * time.Millisecond) // 模拟工作
results <- fmt.Sprintf("Worker %d finished task %d", id, task)
}
}

/*
// Usage:
func main() {
numTasks := 10
numWorkers := 3

tasks := make(chan int, numTasks)
results := make(chan string, numTasks)

var wg sync.WaitGroup

// 启动 worker goroutine
for i := 1; i <= numWorkers; i++ {
wg.Add(1)
go func(id int) {
defer wg.Done()
goroutine_channel.Worker(id, tasks, results)
}(i)
}

// 分发任务
for i := 1; i <= numTasks; i++ {
tasks <- i
}
close(tasks) // 关闭任务通道,表示没有更多任务了

// 等待所有 worker 完成
wg.Wait()
close(results) // 关闭结果通道

// 收集结果
for result := range results {
fmt.Println(result)
}
fmt.Println("All tasks completed.")
}
*/

5.2 Context 模式

Go 语言的 context 包用于在 API 边界之间携带截止时间、取消信号和其他请求范围的值。它在处理超时、取消请求、链路追踪等方面非常有用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
package context_pattern

import (
"context"
"fmt"
"time"
)

func DoWork(ctx context.Context) error {
select {
case <-time.After(2 * time.Second):
fmt.Println("Task completed successfully.")
return nil
case <-ctx.Done():
// 当 context 被取消或超时时,会收到信号
fmt.Println("Task cancelled or timed out:", ctx.Err())
return ctx.Err()
}
}

/*
// Usage:
func main() {
// 示例 1: 超时
fmt.Println("--- Context with Timeout ---")
ctxTimeout, cancelTimeout := context.WithTimeout(context.Background(), 1*time.Second)
defer cancelTimeout()
err := context_pattern.DoWork(ctxTimeout)
if err != nil {
fmt.Println("Error:", err)
}

time.Sleep(500 * time.Millisecond) // 稍微等待一下

// 示例 2: 取消
fmt.Println("\n--- Context with Cancel ---")
ctxCancel, cancelCancel := context.WithCancel(context.Background())
go func() {
time.Sleep(1 * time.Second) // 0.5秒后取消任务
cancelCancel()
}()
err = context_pattern.DoWork(ctxCancel)
if err != nil {
fmt.Println("Error:", err)
}
}
*/

六、总结

Go 语言的设计模式是其独特编程哲学和语言特性(尤其是接口、组合、并发原语)的体现。

  • 创建型模式:通常利用函数和接口来抽象创建过程,sync.Once 是实现单例的关键。
  • 结构型模式:通过接口和结构体嵌入来实现对象的组合和间接访问。
  • 行为型模式:关注对象间的通信,Go 的 Channel 和 Goroutine 为实现并发行为模式提供了强大的原生支持。
  • Go 惯用法context 包用于跨 API 边界传递取消信号和截止时间,Goroutine 和 Channel 是 Go 并发编程的基石,而非传统 OOP 的设计模式。

在学习 Go 语言设计模式时,应秉持 Go 的“实用主义”精神,避免盲目套用传统设计模式,而是结合 Go 的语言特性,选择最简洁、最 Go 风格的解决方案。