Go 语言自带设计模式

本文转载自微信公众号「洋芋编程」,作者蛮荆。转载本文请联系洋芋编程公众号 。
在软件工程中,设计模式(design pattern)是对软件设计中普遍存在(反复出现)的各种问题,所提出的解决方案 。-- 维基百科
和传统的 GOF, JAVA, C# 教科书式的 设计模式 不同,Go 语言设计从一开始就力求简洁,有其他编程语言基础的读者在学习和使用 Go 语言时,万万不可按图索骥、生搬硬套,简单的事情复杂化 。
本文带领大家一起看一下,Go 语言标准库中自带的 编程设计模式 。
单例模式确保一个类只有一个实例,并提供对该实例的全局访问 。
通过使用标准库中的 sync.Once 对业务对象进行简单封装,即可实现 单例模式,简单安全高效 。
package mainimport "sync"var (oncesync.Onceinstance Singleton)// Singleton 业务对象type Singleton struct {}// NewInstance 单例模式方法func NewInstance() Singleton {once.Do(func() {instance = Singleton{}})return instance}func main() {// 调用方代码s1 := NewInstance()s2 := NewInstance()s3 := NewInstance() } 

Go 语言自带设计模式

文章插图
 
Go 标准库单例模式
简单工厂模式Go 语言本身没有 构造方法 特性,工程实践中一般使用 NewXXX 创建新的对象 (XXX 为对象名称),比如标准库中的:
// errors/errors.gofunc New(text string) error {return &errorString{text}}// sync/cond.gofunc NewCond(l Locker) *Cond {return &Cond{L: l}}在这个基础上,如果方法返回的是 interface 的时候,其实就等于是 简单工厂模式,然后再加一层抽象的话,就接近于 抽象工厂模式 。
package main// ConfigParser 配置解析接口type ConfigParser interface {Parse(p []byte)}// JsonParser Json 文件解析器type JsonParser struct {}func (j *JsonParser) Parse(p []byte) {}func newJsonParser() *JsonParser {return &JsonParser{}}// YamlParser Yaml 文件解析器type YamlParser struct {}func (y *YamlParser) Parse(p []byte) {}func newYamlParser() *YamlParser {return &YamlParser{}}type ConfigType uint8const (JsonType ConfigType = 1 << iotaYamlType)// NewConfig 根据不同的类型创建对应的解析器func NewConfig(t ConfigType) ConfigParser {switch t {case JsonType:return newJsonParser()case YamlType:return newYamlParser()default:return nil}}func main() {// 调用方代码jsonParser := NewConfig(JsonType)yamlParser := NewConfig(YamlType)} 
Go 语言自带设计模式

文章插图
 
Go 实现简单工厂模式
对象池模式【Go 语言自带设计模式】通过回收利用对象避免获取和释放资源所需的昂贵成本,我们可以直接使用 sync.Pool 对象来实现功能 。
package mainimport (".NET/http""sync")var (// HTTP Request 对象池reqPool = sync.Pool{New: func() any {return http.Request{}},})func main() {// 调用方代码r1 := reqPool.Get()r2 := reqPool.Get()r3 := reqPool.Get()reqPool.Put(r1)reqPool.Put(r2)reqPool.Put(r3)} 构建模式 (Builder)将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示 。
如果用传统的方法实现 构建模式,对应的 Go 语言代码大致是下面这个样子:
package maintype QueryBuilder interface {Select(table string, columns []string) QueryBuilderWhere(conditions ...string) QueryBuilderGetRawSQL() string}type MySQLQueryBuilder struct {}func (m *MySQLQueryBuilder) Select(table string, columns ...string) QueryBuilder {// 具体实现代码跳过return nil}func (m *MySQLQueryBuilder) Where(conditions ...string) QueryBuilder {// 具体实现代码跳过return nil}func (m *MySQLQueryBuilder) GetRawSQL() string {// 具体实现代码跳过return ""}func main() {// 调用方代码m := &MySQLQueryBuilder{}sql := m.Select("users", "username", "password").Where("id = 100").GetRawSQL()println(sql)} 
Go 语言自带设计模式

文章插图
 
Go 实现构建模式
上面的代码中,通过经典的链式调用来构造出具体的 SQL 语句,但是在 Go 语言中,我们一般使用另外一种模式来实现同样的功能 FUNCTIONAL OPTIONS,这似乎也是 Go 语言中最流行的模式之一 。
package maintype SQL struct {TablestringColumns []stringWhere[]string}type Option func(s *SQL)func Table(t string) Option {// 注意返回值类型return func(s *SQL) {s.Table = t}}func Columns(cs ...string) Option {// 注意返回值类型return func(s *SQL) {s.Columns = cs}}func Where(conditions ...string) Option {// 注意返回值类型return func(s *SQL) {s.Where = conditions}}func NewSQL(options ...Option) *SQL {sql := &SQL{}for _, option := range options {option(sql)}return sql}func main() {// 调用方代码sql := NewSQL(Table("users"),Columns("username", "password"),Where("id = 100"),)println(sql)}


推荐阅读