| name | Go语言模式 |
| description | 当应用Go语言设计模式时,分析并发模式,优化性能策略,解决架构问题。验证模式实现,设计系统架构,和最佳实践。 |
| license | MIT |
Go语言模式技能
概述
Go语言提供了独特的并发模型和简洁的语法结构,使得某些设计模式在Go中有着特殊的实现方式。不当的模式应用会导致代码复杂、性能低下、维护困难。在选择和实现设计模式前需要仔细分析Go语言特性。
核心原则: 好的Go模式应该简洁明了、并发安全、性能优良、易于维护。坏的Go模式会过度抽象、性能损耗、难以理解。
何时使用
始终:
- 设计系统架构时
- 处理并发编程时
- 优化代码结构时
- 提升代码复用时
- 解决设计问题时
- 团队协作开发时
触发短语:
- "Go中如何实现单例模式?"
- "Go并发模式最佳实践"
- "Go语言设计模式应用"
- "如何处理Go中的错误?"
- "Go性能优化模式"
- "Go微服务架构模式"
Go语言模式技能功能
创建型模式
- 单例模式(Singleton)
- 工厂模式(Factory)
- 建造者模式(Builder)
- 原型模式(Prototype)
- 依赖注入(Dependency Injection)
结构型模式
- 适配器模式(Adapter)
- 装饰器模式(Decorator)
- 代理模式(Proxy)
- 组合模式(Composite)
- 外观模式(Facade)
行为型模式
- 观察者模式(Observer)
- 策略模式(Strategy)
- 命令模式(Command)
- 状态模式(State)
- 责任链模式(Chain of Responsibility)
Go特有模式
- Goroutine模式
- Channel模式
- Select模式
- Context模式
- Error处理模式
常见问题
并发问题
设计问题
-
问题: 过度使用全局变量
-
原因: 缺乏依赖注入意识
-
解决: 使用依赖注入模式管理对象生命周期
-
问题: 错误处理不一致
-
原因: 缺乏统一的错误处理策略
-
解决: 实现统一的错误处理模式
代码示例
单例模式实现
package singleton
import (
"sync"
)
type DatabaseConnection struct {
connection string
}
var (
instance *DatabaseConnection
once sync.Once
)
func GetDatabaseConnection() *DatabaseConnection {
once.Do(func() {
instance = &DatabaseConnection{
connection: "mysql://localhost:3306/mydb",
}
})
return instance
}
func ExampleSingleton() {
db1 := GetDatabaseConnection()
db2 := GetDatabaseConnection()
println(db1 == db2)
}
工厂模式实现
package factory
import "fmt"
type Animal interface {
Speak() string
}
type Dog struct{}
func (d Dog) Speak() string {
return "汪汪"
}
type Cat struct{}
func (c Cat) Speak() string {
return "喵喵"
}
func CreateAnimal(animalType string) Animal {
switch animalType {
case "dog":
return Dog{}
case "cat":
return Cat{}
default:
return nil
}
}
func ExampleFactory() {
dog := CreateAnimal("dog")
cat := CreateAnimal("cat")
fmt.Println(dog.Speak())
fmt.Println(cat.Speak())
}
观察者模式实现
package observer
import (
"fmt"
"sync"
)
type Observer interface {
Update(data interface{})
}
type Subject interface {
Register(observer Observer)
Unregister(observer Observer)
Notify(data interface{})
}
type WeatherStation struct {
observers []Observer
mutex sync.RWMutex
temperature float64
}
func NewWeatherStation() *WeatherStation {
return &WeatherStation{
observers: make([]Observer, 0),
}
}
func (ws *WeatherStation) Register(observer Observer) {
ws.mutex.Lock()
defer ws.mutex.Unlock()
ws.observers = append(ws.observers, observer)
}
func (ws *WeatherStation) Unregister(observer Observer) {
ws.mutex.Lock()
defer ws.mutex.Unlock()
for i, obs := range ws.observers {
if obs == observer {
ws.observers = append(ws.observers[:i], ws.observers[i+1:]...)
break
}
}
}
func (ws *WeatherStation) Notify(data interface{}) {
ws.mutex.RLock()
defer ws.mutex.RUnlock()
for _, observer := range ws.observers {
observer.Update(data)
}
}
SetTemperature(temp ) {
ws.temperature = temp
ws.Notify(ws.temperature)
}
TemperatureDisplay {
name
}
Update(data {}) {
fmt.Printf(, td.name, data.())
}
{
station := NewWeatherStation()
display1 := TemperatureDisplay{name: }
display2 := TemperatureDisplay{name: }
station.Register(display1)
station.Register(display2)
station.SetTemperature()
}
Worker Pool模式
package workerpool
import (
"fmt"
"sync"
"time"
)
type Task interface {
Execute() error
}
type PrintTask struct {
message string
}
func (pt PrintTask) Execute() error {
fmt.Println(pt.message)
return nil
}
type WorkerPool struct {
tasks chan Task
workers int
wg sync.WaitGroup
quit chan bool
}
func NewWorkerPool(workers int) *WorkerPool {
return &WorkerPool{
tasks: make(chan Task, workers*2),
workers: workers,
quit: make(chan bool),
}
}
func (wp *WorkerPool) Start() {
for i := 0; i < wp.workers; i++ {
wp.wg.Add(1)
go wp.worker(i)
}
}
func (wp *WorkerPool) worker(id int) {
defer wp.wg.Done()
for {
{
task := <-wp.tasks:
err := task.Execute(); err != {
fmt.Printf(, id, err)
}
<-wp.quit:
fmt.Printf(, id)
}
}
}
Submit(task Task) {
wp.tasks <- task
}
Stop() {
(wp.quit)
wp.wg.Wait()
(wp.tasks)
}
{
pool := NewWorkerPool()
pool.Start()
pool.Stop()
i := ; i < ; i++ {
task := PrintTask{message: fmt.Sprintf(, i)}
pool.Submit(task)
}
time.Sleep(time.Second)
}
Context模式实现
package contextpattern
import (
"context"
"fmt"
"time"
)
func LongRunningOperation(ctx context.Context, duration time.Duration) error {
select {
case <-time.After(duration):
fmt.Println("操作完成")
return nil
case <-ctx.Done():
fmt.Println("操作被取消:", ctx.Err())
return ctx.Err()
}
}
func OperationWithTimeout(timeout time.Duration) error {
ctx, cancel := context.WithTimeout(context.Background(), timeout)
defer cancel()
return LongRunningOperation(ctx, 2*time.Second)
}
func OperationWithCancel() error {
ctx, cancel := context.WithCancel(context.Background())
go func() {
time.Sleep(1 * time.Second)
cancel()
}()
return LongRunningOperation(ctx, 5*time.Second)
}
func ExampleContext() {
fmt.Println("=== 带超时的操作 ===")
err := OperationWithTimeout( * time.Second)
err != {
fmt.Println(, err)
}
fmt.Println()
err = OperationWithCancel()
err != {
fmt.Println(, err)
}
}
错误处理模式
package errorpattern
import (
"errors"
"fmt"
)
type AppError struct {
Code int
Message string
Cause error
}
func (e AppError) Error() string {
if e.Cause != nil {
return fmt.Sprintf("Code: %d, Message: %s, Cause: %v",
e.Code, e.Message, e.Cause)
}
return fmt.Sprintf("Code: %d, Message: %s", e.Code, e.Message)
}
func (e AppError) Unwrap() error {
return e.Cause
}
const (
ErrCodeNotFound = 404
ErrCodeInvalidInput = 400
ErrCodeInternal = 500
)
func NewNotFoundError(message string, cause error) error {
return AppError{
Code: ErrCodeNotFound,
Message: message,
Cause: cause,
}
}
func NewInvalidInputError(message string) error {
return AppError{
Code: ErrCodeInvalidInput,
Message: message,
}
}
func (, ) {
id <= {
, NewInvalidInputError()
}
id == {
, NewNotFoundError(, errors.New())
}
fmt.Sprintf(, id),
}
{
err == {
}
appErr AppError
errors.As(err, &appErr) {
appErr.Code {
ErrCodeNotFound:
fmt.Printf(, appErr.Message)
ErrCodeInvalidInput:
fmt.Printf(, appErr.Message)
ErrCodeInternal:
fmt.Printf(, appErr.Message)
:
fmt.Printf(, appErr.Message)
}
} {
fmt.Printf(, err)
}
}
{
fmt.Println()
user, err := FindUser()
err != {
HandleError(err)
} {
fmt.Println(, user)
}
_, err = FindUser()
HandleError(err)
_, err = FindUser()
HandleError(err)
}
管道模式实现
package pipeline
import (
"fmt"
"sync"
)
type PipelineFunc func(interface{}) (interface{}, error)
type Pipeline struct {
stages []PipelineFunc
}
func NewPipeline() *Pipeline {
return &Pipeline{
stages: make([]PipelineFunc, 0),
}
}
func (p *Pipeline) AddStage(stage PipelineFunc) *Pipeline {
p.stages = append(p.stages, stage)
return p
}
func (p *Pipeline) Execute(input interface{}) (interface{}, error) {
var err error
result := input
for i, stage := range p.stages {
result, err = stage(result)
if err != nil {
return nil, fmt.Errorf("阶段 %d 执行失败: %w", i, err)
}
}
return result, nil
}
type ConcurrentPipeline struct {
stages []PipelineFunc
workers int
}
func NewConcurrentPipeline *ConcurrentPipeline {
&ConcurrentPipeline{
stages: ([]PipelineFunc, ),
workers: workers,
}
}
AddStage(stage PipelineFunc) *ConcurrentPipeline {
cp.stages = (cp.stages, stage)
cp
}
Execute(inputs []{}) ([]{}, ) {
wg sync.WaitGroup
results := ([]{}, (inputs))
errors := ([], (inputs))
workChan := ( , (inputs))
i := ; i < cp.workers; i++ {
wg.Add()
{
wg.Done()
index := workChan {
result, err := cp.processInput(inputs[index])
results[index] = result
errors[index] = err
}
}()
}
i := inputs {
workChan <- i
}
(workChan)
wg.Wait()
_, err := errors {
err != {
, err
}
}
results,
}
processInput(input {}) ({}, ) {
result := input
err
_, stage := cp.stages {
result, err = stage(result)
err != {
, err
}
}
result,
}
({}, ) {
str, ok := input.()
!ok {
, fmt.Errorf()
}
str == {
, fmt.Errorf()
}
str,
}
({}, ) {
str := input.()
fmt.Sprintf(, str),
}
({}, ) {
str := input.()
fmt.Sprintf(, str),
}
{
fmt.Println()
pipeline := NewPipeline()
pipeline.AddStage(ValidateInput)
pipeline.AddStage(Transform)
pipeline.AddStage(FormatOutput)
result, err := pipeline.Execute()
err != {
fmt.Println(, err)
} {
fmt.Println(, result)
}
fmt.Println()
inputs := []{}{
, , , , ,
}
concurrentPipeline := NewConcurrentPipeline()
concurrentPipeline.AddStage(ValidateInput)
concurrentPipeline.AddStage(Transform)
concurrentPipeline.AddStage(FormatOutput)
results, err := concurrentPipeline.Execute(inputs)
err != {
fmt.Println(, err)
} {
i, result := results {
fmt.Printf(, i+, result)
}
}
}
最佳实践
模式选择原则
- 简洁优先: 选择最简单有效的解决方案
- Go语言特性: 充分利用Go的并发和接口特性
- 性能考虑: 避免不必要的抽象和性能损耗
- 可读性: 代码应该易于理解和维护
并发编程
- Goroutine管理: 使用Context控制生命周期
- Channel使用: 避免死锁和数据竞争
- 同步机制: 合理使用Mutex和WaitGroup
- 错误处理: 在并发中正确处理错误
代码组织
- 包设计: 保持包的职责单一
- 接口设计: 接口应该小而专注
- 依赖管理: 使用依赖注入减少耦合
- 测试覆盖: 为模式实现编写充分测试
相关技能
- rust-systems - 系统编程模式
- python-advanced - 高级编程模式
- javascript-es6 - 现代JavaScript模式
- backend - 后端架构模式
- performance-optimization - 性能优化策略