Kennem's Blog
  • 🏠主页
  • 🔍搜索
  • 📚文章
  • ⏱时间轴
  • 🔖标签
  • 🗂️分类
  • 🙋🏻‍♂️关于
主页 » 🧩 标签

GoLang

Go ——设计模式

Go ——设计模式 simple_factory 简单工厂 package test const ( APITypeHi = iota + 1 APITypeHello ) type Greeting interface { Say(msg string) string } func NewGreeting(t int) Greeting { if t == APITypeHi { return &Hi{} } else if t == APITypeHello { return &Hello{} } return nil } type Hi struct{} func (h *Hi) Say(msg string) string { return "Hi! " + msg } type Hello struct{} func (h *Hello) Say(msg string) string { return "Hello! " + msg } package test import "testing" func TestGreeting(t *testing.T) { tests := []struct { name string apiType int msg string expected string }{ {"HiType", APITypeHi, "2026", "Hi! 2026"}, {"HelloType", APITypeHello, "2026", "Hello! 2026"}, {"NilType", 999, "2026", ""}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { g := NewGreeting(tt.apiType) if g == nil { if tt.expected != "" { t.Errorf("NewGreeting(%d) returned nil, expected non-nil", tt.apiType) } return } out := g.Say(tt.msg) if out != tt.expected { t.Errorf("Say() = %q, want %q", out, tt.expected) } }) } } facade 装饰器 package test type API interface { Test() string } func NewAPI() API { return &apiImpl{ a: NewAImpl(), b: NewBImpl(), } } type apiImpl struct { a AModule b BModule } func (api *apiImpl) Test() string { // 把两部分结果拼接返回 return api.a.TestA() + api.b.TestB() } // --- AModule --- type AModule interface { TestA() string } type AImpl struct{} func NewAImpl() AModule { return &AImpl{} } func (a *AImpl) TestA() string { return "testA ... " } // --- BModule --- type BModule interface { TestB() string } type BImpl struct{} func NewBImpl() BModule { return &BImpl{} } func (b *BImpl) TestB() string { return "testB ... " } package test import "testing" func TestFacade(t *testing.T) { api := NewAPI() out := api.Test() expected := "testA ... testB ... " if out != expected { t.Errorf("API Test() = %q, want %q", out, expected) } } adapter 适配器 package test type Adapter interface { Request() string } func NewAdapter(adaptee Adaptee) Adapter { return &adapter{ adaptee: adaptee, } } type adapter struct { adaptee Adaptee } func (a *adapter) Request() string { return a.adaptee.SpecificRequest() } // --- Adaptee 接口与实现 --- type Adaptee interface { SpecificRequest() string } type adaptee struct{} func NewAdaptee() Adaptee { return &adaptee{} } func (a *adaptee) SpecificRequest() string { return "specific request called" } package test import "testing" func TestAdapter(t *testing.T) { adaptee := NewAdaptee() adapter := NewAdapter(adaptee) out := adapter.Request() expected := "specific request called" if out != expected { t.Errorf("Adapter Request() = %q, want %q", out, expected) } } singleton 单例设计模式 package test import "sync" type Singleton interface { Foo() } type singleton struct{} func (s *singleton) Foo() {} var ( once sync.Once instance Singleton ) func GetSingleton() Singleton { once.Do(func() { instance = &singleton{} }) return instance } package test import ( "sync" "testing" ) const goroutineCount = 1000 // 单线程测试 func TestSingletonSingleThread(t *testing.T) { a := GetSingleton() b := GetSingleton() if a != b { t.Fatalf("Singleton failed: a != b") } } // 并发测试 func TestSingletonConcurrent(t *testing.T) { start := make(chan struct{}) instances := [goroutineCount]Singleton{} wg := sync.WaitGroup{} wg.Add(goroutineCount) for i := 0; i < goroutineCount; i++ { go func(idx int) { <-start instances[idx] = GetSingleton() wg.Done() }(i) } // 同时启动所有 goroutine close(start) wg.Wait() // 验证所有实例都相等 for i := 0; i < goroutineCount-1; i++ { if instances[i] != instances[i+1] { t.Fatalf("Singleton failed: instances[%d] != instances[%d]", i, i+1) } } } factory_method 工厂方法 package test // Operator 接口 type Operator interface { SetA(int) SetB(int) Result() int } // 工厂接口 type OperatorFactory interface { Create() Operator } // OperatorBase 提供公共字段与方法 type OperatorBase struct { a, b int } func (o *OperatorBase) SetA(a int) { o.a = a } func (o *OperatorBase) SetB(b int) { o.b = b } // PlusOperator type PlusOperator struct{ *OperatorBase } func (p *PlusOperator) Result() int { return p.a + p.b } // PlusOperatorFactory type PlusOperatorFactory struct{} func (PlusOperatorFactory) Create() Operator { return &PlusOperator{&OperatorBase{}} } // MinusOperator type MinusOperator struct{ *OperatorBase } func (m *MinusOperator) Result() int { return m.a - m.b } // MinusOperatorFactory type MinusOperatorFactory struct{} func (MinusOperatorFactory) Create() Operator { return &MinusOperator{&OperatorBase{}} } package test import "testing" func TestOperatorFactory(t *testing.T) { tests := []struct { name string factory OperatorFactory a, b int expected int }{ {"Plus", &PlusOperatorFactory{}, 1001, 10, 1011}, {"Minus", &MinusOperatorFactory{}, 1001, 10, 991}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { op := tt.factory.Create() op.SetA(tt.a) op.SetB(tt.b) if got := op.Result(); got != tt.expected { t.Fatalf("expected %v, got %v", tt.expected, got) } }) } } abstract_factory 抽象工厂 package test // OrderMainDAO 为订单主记录 type OrderMainDAO interface { SaveOrderMain() string } // OrderDetailDAO 为订单详情纪录 type OrderDetailDAO interface { SaveOrderDetail() string } // DAOFactory DAO 抽象工厂接口 type DAOFactory interface { CreateOrderMainDAO() OrderMainDAO CreateOrderDetailDAO() OrderDetailDAO } // ------------------ RDB 实现 ------------------ type RDBMainDAO struct{} func (*RDBMainDAO) SaveOrderMain() string { return "rdb main save" } type RDBDetailDAO struct{} func (*RDBDetailDAO) SaveOrderDetail() string { return "rdb detail save" } type RDBDAOFactory struct{} func (*RDBDAOFactory) CreateOrderMainDAO() OrderMainDAO { return &RDBMainDAO{} } func (*RDBDAOFactory) CreateOrderDetailDAO() OrderDetailDAO { return &RDBDetailDAO{} } // ------------------ XML 实现 ------------------ type XMLMainDAO struct{} func (*XMLMainDAO) SaveOrderMain() string { return "xml main save" } type XMLDetailDAO struct{} func (*XMLDetailDAO) SaveOrderDetail() string { return "xml detail save" } type XMLDAOFactory struct{} func (*XMLDAOFactory) CreateOrderMainDAO() OrderMainDAO { return &XMLMainDAO{} } func (*XMLDAOFactory) CreateOrderDetailDAO() OrderDetailDAO { return &XMLDetailDAO{} } package test import "testing" // GetMainAndDetail 调用工厂生成 DAO 并返回结果 func GetMainAndDetail(factory DAOFactory) (mainResult, detailResult string) { mainResult = factory.CreateOrderMainDAO().SaveOrderMain() detailResult = factory.CreateOrderDetailDAO().SaveOrderDetail() return } func TestAbstractFactory(t *testing.T) { tests := []struct { name string factory DAOFactory expectedMain string expectedDetail string }{ {"RDBFactory", &RDBDAOFactory{}, "rdb main save", "rdb detail save"}, {"XMLFactory", &XMLDAOFactory{}, "xml main save", "xml detail save"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { mainResult, detailResult := GetMainAndDetail(tt.factory) if mainResult != tt.expectedMain { t.Errorf("mainResult = %q, want %q", mainResult, tt.expectedMain) } if detailResult != tt.expectedDetail { t.Errorf("detailResult = %q, want %q", detailResult, tt.expectedDetail) } }) } } builder 建造者 package test // Builder 是生成器接口 type Builder interface { Part1() Part2() Part3() } // Director 构建指挥者 type Director struct { builder Builder } // NewDirector ... func NewDirector(builder Builder) *Director { return &Director{builder: builder} } // Construct 构建产品 func (d *Director) Construct() { d.builder.Part1() d.builder.Part2() d.builder.Part3() } // ---------------- Builder1 ---------------- type Builder1 struct { result string } func (b *Builder1) Part1() { b.result += "1" } func (b *Builder1) Part2() { b.result += "2" } func (b *Builder1) Part3() { b.result += "3" } func (b *Builder1) GetResult() string { return b.result } // ---------------- Builder2 ---------------- type Builder2 struct { result int } func (b *Builder2) Part1() { b.result += 1 } func (b *Builder2) Part2() { b.result += 2 } func (b *Builder2) Part3() { b.result += 3 } func (b *Builder2) GetResult() int { return b.result } package test import "testing" func TestBuilder(t *testing.T) { tests := []struct { name string builder Builder expected interface{} getRes func() interface{} }{ { name: "Builder1", builder: &Builder1{}, expected: "123", getRes: func() interface{} { return (&Builder1{}).GetResult() }, }, { name: "Builder2", builder: &Builder2{}, expected: 6, getRes: func() interface{} { return (&Builder2{}).GetResult() }, }, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { d := NewDirector(tt.builder) d.Construct() var actual interface{} switch b := tt.builder.(type) { case *Builder1: actual = b.GetResult() case *Builder2: actual = b.GetResult() default: t.Fatalf("unsupported builder type") } if actual != tt.expected { t.Fatalf("expected %v, got %v", tt.expected, actual) } }) } } prototype 原型模式 package test // Cloneable 是原型对象需要实现的接口 type Cloneable interface { Clone() Cloneable } type PrototypeManager struct { prototypes map[string]Cloneable } func NewPrototypeManager() *PrototypeManager { return &PrototypeManager{ prototypes: make(map[string]Cloneable), } } // Get 返回指定名称的原型克隆对象 func (p *PrototypeManager) Get(name string) Cloneable { proto, ok := p.prototypes[name] if !ok { return nil } return proto.Clone() } // Set 注册原型对象 func (p *PrototypeManager) Set(name string, prototype Cloneable) { p.prototypes[name] = prototype } package test import "testing" // Type1 原型类型1 type Type1 struct { Name string } func (t *Type1) Clone() Cloneable { tc := *t return &tc } // Type2 原型类型2 type Type2 struct { Name string } func (t *Type2) Clone() Cloneable { tc := *t return &tc } func setupManager() *PrototypeManager { manager := NewPrototypeManager() manager.Set("t1", &Type1{Name: "type1"}) manager.Set("t2", &Type2{Name: "type2"}) return manager } func TestPrototypeClone(t *testing.T) { manager := setupManager() tests := []struct { name string prototype string expected string typeAssert string // 用于类型断言检查 }{ {"Type1 Clone", "t1", "type1", "Type1"}, {"Type2 Clone", "t2", "type2", "Type2"}, } for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { obj := manager.Get(tt.prototype) if obj == nil { t.Fatalf("Get(%s) returned nil", tt.prototype) } // 验证克隆对象不是原对象 original := manager.prototypes[tt.prototype] if obj == original { t.Fatalf("Clone returned the same object as original") } // 类型断言并检查字段 switch tt.typeAssert { case "Type1": casted := obj.(*Type1) if casted.Name != tt.expected { t.Fatalf("expected %s, got %s", tt.expected, casted.Name) } case "Type2": casted := obj.(*Type2) if casted.Name != tt.expected { t.Fatalf("expected %s, got %s", tt.expected, casted.Name) } } }) } } proxy 代理 package test type Subject interface { Do() string } type RealSubject struct{} func (RealSubject) Do() string { return "real" } type Proxy struct { real Subject } func NewProxy(real Subject) Subject { return &Proxy{real: real} } func (p *Proxy) Do() string { res := "pre:" res += p.real.Do() res += ":after" return res } package test import "testing" func TestProxy(t *testing.T) { real := &RealSubject{} sub := NewProxy(real) res := sub.Do() if res != "pre:real:after" { t.Fatalf("expect pre:real:after, got %s", res) } } observer 观察者 package test type Subject struct { observers []Observer context string } func NewSubject() *Subject { return &Subject{ observers: make([]Observer, 0), } } type Observer interface { Update(*Subject) } func (s *Subject) Attach(o Observer) { s.observers = append(s.observers, o) } func (s *Subject) notify() { for _, o := range s.observers { o.Update(s) } } func (s *Subject) UpdateContext(context string) { s.context = context s.notify() } func (s *Subject) Context() string { return s.context } type Reader struct { name string received []string } func NewReader(name string) *Reader { return &Reader{ name: name, received: make([]string, 0), } } func (r *Reader) Update(s *Subject) { r.received = append(r.received, s.Context()) } func (r *Reader) Received() []string { return r.received } func (r *Reader) Name() string { return r.name } package test import "testing" func TestObserver(t *testing.T) { subject := NewSubject() r1 := NewReader("reader1") r2 := NewReader("reader2") r3 := NewReader("reader3") subject.Attach(r1) subject.Attach(r2) subject.Attach(r3) subject.UpdateContext("observer mode") readers := []*Reader{r1, r2, r3} for _, r := range readers { received := r.Received() if len(received) != 1 { t.Fatalf("%s expect 1 update got %d", r.Name(), len(received)) } if received[0] != "observer mode" { t.Fatalf("%s expect observer mode got %s", r.Name(), received[0]) } } }

2026-01-02 · 4 分钟 · 1948 字 · updated: 2026-01-02 · ShowGuan

Go 开发框架三件套

Go 开发框架三件套 1. Gorm - 强大的 ORM 框架深度扩展 1.1 基本使用增强版 1.1.1 完整 CRUD 操作示例 // 创建记录(批量插入) users := []User{ {Name: "Alice", Age: 25}, {Name: "Bob", Age: 30}, {Name: "Charlie", Age: 35}, } db.Create(&users) // 一次性插入所有记录 // 查询记录(带条件) var activeUsers []User db.Where("status = ? AND age > ?", "active", 25). Order("created_at desc"). Limit(10). Offset(0). Find(&activeUsers) // 更新多个字段 db.Model(&User{}).Where("role = ?", "admin"). Updates(map[string]interface{}{ "age": 40, "status": "inactive", }) // 删除记录(带条件) db.Where("email LIKE ?", "%@test.com").Delete(&User{}) 1.1.2 高级查询技巧 // 子查询 subQuery := db.Select("AVG(age)").Where("department = ?", "IT").Table("users") db.Where("age > (?)", subQuery).Find(&users) // 原生 SQL 执行 db.Exec("UPDATE users SET balance = balance * ? WHERE level > ?", 1.1, 3) // 查询结果映射到自定义结构体 type UserProfile struct { Name string Email string } db.Model(&User{}).Select("name, email").Scan(&UserProfile{}) 1.2 软删除进阶实践 1.2.1 自定义删除字段 type CustomModel struct { ID uint `gorm:"primarykey"` CreatedAt time.Time UpdatedAt time.Time Deleted gorm.DeletedAt `gorm:"index;column:deleted_at"` } type Product struct { CustomModel Name string Price float64 } // 使用自定义删除字段 db.Where("price < ?", 100).Delete(&Product{}) 1.2.2 软删除与关联关系 type Company struct { gorm.Model Name string Products []Product `gorm:"foreignKey:CompanyID"` } // 级联软删除 db.Select("Products").Delete(&company) 1.3 事务管理增强 1.3.1 分布式事务示例(Saga模式) // 创建订单事务 err := db.Transaction(func(tx *gorm.DB) error { // 扣减库存 if err := tx.Model(&Inventory{}). Where("product_id = ?", order.ProductID). Update("quantity", gorm.Expr("quantity - ?", order.Quantity)). Error; err != nil { return err } // 创建订单 if err := tx.Create(&order).Error; err != nil { return err } // 调用支付服务(外部系统) if err := paymentClient.Charge(order.Total); err != nil { return err // 自动回滚 } return nil }) 1.3.2 事务隔离级别配置 // 设置事务隔离级别为可重复读 tx := db.Set("gorm:query_options", "SET TRANSACTION ISOLATION LEVEL REPEATABLE READ").Begin() // 在事务中执行操作 tx.Model(&User{}).Where("id = ?", 1).Update("balance", gorm.Expr("balance - ?", 100)) tx.Commit() 1.4 Hook 全生命周期管理 1.4.1 完整 Hook 列表及执行顺序 type Order struct { gorm.Model Status string TotalPrice float64 } // 创建流程 func (o *Order) BeforeCreate(tx *gorm.DB) error { o.Status = "pending" return nil } func (o *Order) AfterCreate(tx *gorm.DB) error { tx.Model(o).Update("order_no", generateOrderNo()) return nil } // 更新流程 func (o *Order) BeforeUpdate(tx *gorm.DB) error { if o.Status == "shipped" { o.TotalPrice *= 1.1 // 增加运费 } return nil } 1.4.2 审计日志实现 func (u *User) BeforeUpdate(tx *gorm.DB) error { if tx.Statement.Changed("Email") { oldEmail := tx.Statement.Old("Email").(string) newEmail := tx.Statement.New("Email").(string) audit := AuditLog{ UserID: u.ID, Action: "UPDATE_EMAIL", OldValue: oldEmail, NewValue: newEmail, } tx.Create(&audit) } return nil } 1.5 性能优化深度指南 1.5.1 连接池最佳配置 sqlDB, err := db.DB() if err != nil { panic("failed to get database handle") } // 连接池配置 sqlDB.SetMaxIdleConns(20) // 空闲连接数 sqlDB.SetMaxOpenConns(100) // 最大打开连接数 sqlDB.SetConnMaxLifetime(time.Hour) // 连接最大生命周期 sqlDB.SetConnMaxIdleTime(30*time.Minute) // 空闲连接最大存活时间 1.5.2 索引优化策略 type Product struct { gorm.Model SKU string `gorm:"index:idx_sku,unique"` Category string `gorm:"index:idx_category"` Price float64 } // 复合索引 db.Model(&Order{}).AddIndex("idx_status_created", "status", "created_at") // 表达式索引(PostgreSQL) db.Exec("CREATE INDEX idx_lower_name ON users ((lower(name)))") 1.6 生态扩展实践 1.6.1 常用插件示例 // 分页插件 import "gorm.io/plugin/pagination" db.Use(pagination.Register) var users []User result := db.Scopes(pagination.Paginate(page, pageSize)).Find(&users) // 数据加密插件 import "github.com/go-gorm/gorm/v2/plugin/crypto" db.Use(crypto.NewCryptoPlugin(crypto.Config{ Keys: [][]byte{[]byte("32-byte-long-secret-key-here")}, })) 1.6.2 多数据库支持 // MySQL 配置 mysqlDB, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) // PostgreSQL 配置 postgresDB, err := gorm.Open(postgres.Open(dsn), &gorm.Config{ NamingStrategy: schema.NamingStrategy{ TablePrefix: "tbl_", }, }) // SQLite 配置 sqliteDB, err := gorm.Open(sqlite.Open("gorm.db"), &gorm.Config{ DisableForeignKeyConstraintWhenMigrating: true, }) 1.7 高级特性 1.7.1 多租户架构实现 // 基于 schema 的多租户 db.Use(multitenancy.New(multitenancy.Config{ TenantKey: "X-Tenant-ID", Resolver: func(c *multitenancy.Context) string { return c.Request.Header.Get("X-Tenant-ID") }, })) // 自动路由到对应 schema db.Scopes(func(d *gorm.DB) *gorm.DB { return d.Table("tenant_" + tenantID + ".users") }) 1.7.2 版本化迁移 // 使用 Atlas 迁移工具 // 创建迁移文件 migrate create --dir migrations --format golang add_users_table // 执行迁移 migrate apply --dir migrations --dialect mysql 1.8 最佳实践总结 查询优化: ...

2025-01-26 · 3 分钟 · 1427 字 · updated: 2025-01-26 · ShowGuan

Go 并发与依赖管理

Go 并发与依赖管理 01 并发与并行 Go 语言以简洁、轻量级的方式支持并发编程,通过 Goroutine 和 Channel 可以充分利用多核 CPU,提高程序执行效率。理解 Go 的并发模型对于写出高效、稳定的程序至关重要。 ...

2025-01-25 · 11 分钟 · 5139 字 · updated: 2025-01-25 · ShowGuan

Go 高质量编程与性能调优

Go 高质量编程与性能调优 本文深入探讨 Go 语言的高质量编程和性能调优,结合具体示例,帮助你编写正确可靠、简洁清晰的代码,并掌握性能优化的核心方法。 01 高质量编程 高质量代码的目标是正确可靠、简洁清晰。以下是实现高质量编程的关键点。 ...

2025-01-25 · 7 分钟 · 3462 字 · updated: 2025-01-25 · ShowGuan

Go 内存管理与编译器优化

Go 内存管理与编译器优化 本文深入探讨 Go 语言的自动内存管理、垃圾回收机制以及编译器优化技术,结合具体示例和流程图,帮助你理解 Go 内存管理的核心原理和性能优化方法。 ...

2025-01-25 · 7 分钟 · 3196 字 · updated: 2025-01-25 · ShowGuan

Go语言基础

Go语言基础 1. Go语言概述 高性能:适合并发编程,支持高并发、高性能场景。 简洁语法:Go的语法简洁,快速上手,去除了复杂的面向对象特性,保留了函数式编程的一些优势。 丰富标准库:内建强大的标准库,支持网络、文件操作、并发等。 静态链接:生成独立的可执行文件,无需依赖外部库,简化部署。 跨平台:支持Linux、Windows、macOS等多个平台。 垃圾回收:自动管理内存,减少开发人员的负担。 2. 环境搭建 Go安装:官方安装指南 推荐IDE:VSCode、GoLand,或者Gitpod等云开发环境。 Go Module go.mod:用于管理 Go 项目的依赖,记录模块路径、Go 版本和所依赖的包及其版本。 ...

2025-01-25 · 20 分钟 · 9558 字 · updated: 2025-11-02 · ShowGuan
© 2026 Kennem's Blog · Powered by Hugo & PaperMod
👤 Visitors: 👀 Views: