自己做网站前端开发/免费网站制作
文章目录
- 前言
- 一、函数选项模式
- 二、单例模式
- 三、工厂模式
- 四、责任链模式
前言
宿舍每人 温度38℃+ 大寄
设计模式很重要,设计模式其实就是为了解决某一类问题而形成的代码写法,设计模式很多,但是并不是每个都很常用,我们只讲解─些常用的
设计模式分类大家可以参考: https://juejin.cn/post/6908528350986240014
go中最常用的设计模式是函数选项模式, grpc,kratos等等开源项目中比比皆是
有时候一个函数会有很多参数,为了方便函数的使用,我们会给希望给一些参数设定默认值,调用时只需要传与默认值不同的参数即可,类似于python里面的默认参数和字典参数,在java中可以提供多种构造函数,虽然 golang里面既没有默认参数也没有字典参数,但是我们有选项模式
注:函数选项模式是用来构造对象
go中没有构造器,要构造一个对象一般是直接实例化,或者采用NewXX的模式,其中
- 实例化然后复制属性的模式会写很多行代码,虽然可以直接采用A{name:xxx, b:xxx}的模式,但
是如果有个c属性的默认值不是空字符串咋办? - 所以整个过程使用实例化加属性设置的方式会让实例化很麻烦
- 使用new的方式也会有问题:如果可以一个参数设置,如果可以两个参数设置不得不使用
newA,newAandB等等各种组合设置 - 有没有办法可以同时解决上面的问题呢?-函数选项模式
选项模式的应用
从这里可以看到,为了实现选项的功能,我们增加了很多的代码,实现成本相对还是较高的,所以实践中需要根据自己的业务场景去权衡是否需要使用。个人总结满足下面条件可以考虑使用选项模式
- 参数确实比较复杂,影响调用方使用
- 参数确实有比较清晰明确的默认值
- 为参数的后续拓展考虑
在golang 的很多开源项目里面也用到了选项模式,比如 grpc中的 rpc方法就是采用选项模式设计的,除了必填的rpc参数外,还可以一些选项参数,grpc_retry就是通过这个机制实现的,可以实现自动重试功能。
一、函数选项模式
函数选项模式(Functional Options Pattern):
函数选项模式是一种用于函数设计的模式,它允许函数接受可选参数,这些参数可以通过一种简单、灵活的方式进行设置,从而避免出现过多的函数重载。在Go语言中,函数选项模式通常使用可变参数列表结合函数类型参数的方式实现。通过该模式,我们可以更加灵活地控制函数的行为,并且可以方便地扩展函数的功能。
在这个示例代码中,DbOptions
结构体类型定义了用于保存数据库连接选项的字段。为了实现函数选项模式,我们定义了一个名为Option
的函数类型,用于设置DbOptions
结构体中的字段值。WithHost
函数是一个实现了Option
函数类型的具体函数,用于设置数据库连接的主机地址。NewOpts
函数接受任意数量的Option
函数类型的参数,并将其应用于一个DbOptions
结构体类型的实例上。
在NewOpts
函数中,我们首先定义一个带有默认值的DbOptions
结构体类型的实例,并将其保存在dbopts
变量中。接着,我们遍历所有传入的Option
函数类型参数,逐个将其应用于dbopts
变量中的字段。最后,我们返回dbopts
变量的值,这是一个包含了所有设置过的选项的DbOptions
结构体类型实例。
在main
函数中,我们调用NewOpts
函数获取默认选项,并将其打印输出。此时,输出的结果中将包含我们在WithHost
函数中设置的主机地址选项。这种方式可以使得我们在使用该函数时,只需要传递需要设置的选项,而不需要关心默认选项或者选项的顺序。
package mainimport "fmt"type DbOptions struct {Host stringPort intUsername stringPassword stringDBName string
}type Option func(*DbOptions)// 这个函数主要用来设置Host
func WithHost(host string) Option {return func(o *DbOptions) {o.Host = host}
}func NewOpts(opts ...Option) DbOptions {//先实例化号dbOptions,填充上默认值dbopts := &DbOptions{Host: "127.0.0.1",Port: 3306,Username: "root",Password: "123456",DBName: "test",}for _, option := range opts {option(dbopts)}return *dbopts
}func main() {//NewDBClient(WithHost("192.168.0.1"))//opts := NewOpts(WithHost("192.168.0.1"))opts := NewOpts()fmt.Println(opts)//函数选项牧师大量引用了函数,
}
二、单例模式
单例模式(Singleton Pattern):
单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供了一个全局访问点来访问该实例。在Go语言中,单例模式通常使用包级别变量或者全局变量来实现,因为包级别变量只会被初始化一次,而全局变量则是唯一的。
1. 使用sync.Once实现单例模式
在下面的代码中,使用了sync.Once
类型来确保在程序运行时只执行一次初始化逻辑,以创建唯一的DBPool
实例。具体实现步骤如下:
a. 在GetDBPool2
函数中,调用sync.Once
的Do
方法,并将初始化逻辑封装在一个匿名函数中。
b. 在匿名函数中创建DBPool
实例,并将其赋值给dbPoolIns
变量。
c. 返回dbPoolIns
变量。
使用sync.Once
实现的单例模式具有并发安全性,并且无需加锁即可实现懒加载,但需要创建匿名函数,代码稍微有些复杂。
2. 使用sync.Mutex和atomic实现单例模式
在下面的代码中,使用了sync.Mutex
和atomic
两个包来实现单例模式。具体实现步骤如下:
a. 在GetDBPool
函数中,首先判断initialized
变量是否为1,如果是,则直接返回dbPoolIns
变量。
b. 如果initialized
变量不是1,则获取锁,防止其他goroutine
同时执行初始化逻辑。
c. 在获取锁后,再次判断initialized
变量是否为0,如果是,则创建DBPool
实例,并将其赋值给dbPoolIns
变量,然后使用atomic.StoreUint32
函数将initialized
变量设置为1。
d. 释放锁并返回dbPoolIns
变量。
使用sync.Mutex
和atomic
实现的单例模式也具有并发安全性,并且代码比较简单易懂,但需要显式加锁,并且无法实现懒加载。
package mainimport ("sync""sync/atomic"
)type DBPool struct {Host stringPort intUserName string
}var dbPoolIns *DBPool
var lock sync.Mutex
var initialized uint32// 有问题的方法,并发
// 加锁 - 功能上没有问题,但是性能不好
// 高并发下,有bug
// goroutine1 进来,实例化dbPoolIns = &DBPool{}进想到一半,goroutine2进来,读到dbPoolIns != nil,返回dbPoolIns
func GetDBPool() *DBPool {if atomic.LoadUint32(&initialized) == 1 {return dbPoolIns}lock.Lock()defer lock.Unlock()if initialized == 0 {dbPoolIns = &DBPool{}//原子操作 一旦有一个线程执行到了atomic.LoadUint32(&initialized) initialized就会被保护 确保initialized的原子性atomic.StoreUint32(&initialized, 1)}return dbPoolIns
}var once sync.Oncefunc GetDBPool2() *DBPool {once.Do(func() {dbPoolIns = &DBPool{}})return dbPoolIns
}
func main() {}
三、工厂模式
工厂模式(Factory Pattern):
工厂模式是一种创建型设计模式,它提供了一个抽象工厂接口来创建一系列相关的对象,而无需指定具体的类。在Go语言中,工厂模式通常使用接口和结构体的组合来实现,从而实现对不同对象的创建。通过该模式,我们可以更加灵活地创建对象,并且可以方便地扩展对象的种类。
在这个示例中,我们定义了一个名为“Book”的接口,该接口有一个名为“Name”的方法。然后,我们定义了三个具体的书籍类型:ChineseBook、MathBook和EnglishBook,并让它们都实现了“Book”接口的“Name”方法。
接下来,我们定义了一个名为“GetBook”的函数,该函数接受一个字符串参数“name”,并根据名称返回一个具体的书籍类型。我们使用一个简单的 switch 语句来实现这个功能,并在默认情况下返回 nil。
最后,在“main”函数中,我们调用“GetBook”函数,传递不同的书籍名称,并打印出返回的书籍类型。
工厂模式的好处是,在增加新的书籍类型时,我们只需要添加新的具体类型和一个对应的 case 语句,而不需要修改现有的代码。这使得我们的代码更加灵活和可扩展。
在实际应用中,工厂模式可以帮助我们更好地组织和管理代码,并将复杂的对象创建过程封装起来,使得我们的代码更加易于维护和扩展。
package mainimport "fmt"/*
在小明的学校,每一年开学都会发教材,
主要包括语文书、数学书、英语书,还有各种练习试卷。
这一天,小明去领了三本教材,分别是语文书、数学书和英语书,老师忙不过来,指定某个同学去发书,
同学们都去这个同学这里去领书。这个同学就是工厂。
*/
type Book interface {Name() string
}
type chineseBook struct {name string
}func (cb *chineseBook) Name() string {return cb.name
}type mathBook struct {name string
}func (mb *mathBook) Name() string {return mb.name
}type englishBook struct {name string
}func (eb *englishBook) Name() string {return eb.name
}
func GetBook(name string) Book {switch name {case "语文书":return &chineseBook{name: name}case "数学书":return &mathBook{name: name}case "英语书":return &englishBook{name: name}default:return nil}
}
func main() {fmt.Println(GetBook("语文书"))fmt.Println(GetBook("数学书"))
}
四、责任链模式
责任链模式(Chain of Responsibility Pattern):
责任链模式是一种行为型设计模式,它将一系列对象连接在一起,形成一个责任链。当请求被发送到该链上时,每个对象都有机会处理请求或将其传递给下一个对象,直到请求被处理为止。在Go语言中,责任链模式通常使用链表或者数组来实现,从而实现对请求的处理。通过该模式,我们可以更加灵活地处理请求,并且可以方便地扩展处理的对象。
在这个示例中,我们可以将 Assigner 接口看做一个处理器对象,用来处理请求并返回相应的书籍或文献。在 assigner 结构体中,我们实现了 GetBook 和 GetPaper 方法来获取不同类型的书籍或文献。在 chineseBookAssigner 结构体中,我们仅仅处理了语文书籍的请求,而其他类型的请求则会被忽略。这样,如果一个请求需要被处理,它就会被传递给第一个处理器对象,然后沿着处理链一直传递到最后一个处理器对象,直到找到能够处理请求的处理器对象或者到达处理链的末端。
在 main 函数中,我们创建了一个 chineseBookAssigner 对象并调用其 GetBook 方法来获取语文书籍的对象。由于 chineseBookAssigner 只处理语文书籍的请求,所以我们可以看到它成功地返回了一个 chineseBook 对象。而对于其他类型的请求,则会返回 nil。这样,我们就实现了一个简单的责任链模式。
package mainimport "fmt"/*
在小明的学校,每一年开学都会发教材,
主要包括语文书、数学书、英语书,还有各种练习试卷。
这一天,小明去领了三本教材,分别是语文书、数学书和英语书,老师忙不过来,指定某个同学去发书,
同学们都去这个同学这里去领书。这个同学就是工厂。
*/
type Book interface {Name() string
}
type Paper interface {Name() string
}type chineseBook struct {name string
}
type chinesePaper struct {name string
}func (cb *chineseBook) Name() string {return cb.name
}type mathBook struct {name string
}func (mb *mathBook) Name() string {return mb.name
}type englishBook struct {name string
}func (eb *englishBook) Name() string {return eb.name
}type Person struct{}type Assigner interface {GetBook(name string) BookGetpaper(string) Paper
}
type assigner struct{}func (a *assigner) GetBook(name string) Book {switch name {case "语文书":return &chineseBook{name: name}case "数学书":return &mathBook{name: name}case "英语书":return &englishBook{name: name}default:return nil}
}type chineseBookAssigner struct {
}func (cba *chineseBookAssigner) GetBook(name string) Book {if name == "语文书" {return &chineseBook{name: name}}return nil
}
func main() {var a chineseBookAssignerfmt.Println(a.GetBook("语文书"))fmt.Println(a.GetBook("数学书"))
}
相关文章:

【设计模式】go语言中的 [函数选项,单例,工厂,责任链] 常用的设计模式
文章目录前言一、函数选项模式二、单例模式三、工厂模式四、责任链模式前言 宿舍每人 温度38℃+ 大寄 设计模式很重要,设计模式其实就是为了解决某一类问题而形成的代码写法,设计模式很多,但是并不是每个都很常用,我们…...

2017系统分析师案例分析真题背记内容
前言 以下内容仅为个人根据当年系分案例真题问题整理的偏需要记背的考点答案,方便个人背诵和记忆使用。方便文字转语音,所以内容全为纯文字内容,以下内容仅供参考。 背记内容 微服务 微服务中应该包含的内容有:资源、对资源的…...

C++和C的区别
答:从宏观角度和微观角度分析微观角度:函数原型有区别,在c中,函数原型有参数和没有参数是不同的,并且允许申明多个同名的函数,只要他们的参数列表不同或者返回值不同即可,但是在c语言中不能。C引…...

【React教程】一、React简介
一、React简介 React是一个用于构建用户界面的JavaScript库,它是Facebook的内部项目,用来架设Instagram的网站,并于2013年5月开源。React主要用于构建Ul,很多人认为React 是 MVC 中的 V(视图)。由于拥有较高的性能&…...

运动蓝牙耳机什么牌子好,比较好的运动蓝牙耳机推荐
现在市面上的运动蓝牙耳机越来越多,在选择耳机的时候应该如何入手呢?最重要的是需要按照自己的需求来选择,但在耳机的配置上不能忽视的是耳机的防水等级,运动耳机对防水等级的要求更高,这样能够更好地防御汗水浸湿耳机…...

[深入理解SSD系列 闪存实战2.1] NAND FLASH特性串烧 | 不了解闪存特性,你能用好闪存产品吗?
前言 为了利用好闪存, 发挥闪存的优势, 以达到更好的性能和使用寿命, 那自然要求了解闪存特性。 闪存作为一种相对较新的存储介质, 有很多特别的特性。 一.闪存的特性 凡是采用Flash Memory的存储设备,可以统称为闪存存储。我们经常谈的固态硬盘(SSD),可以由volatile/…...

DJI ROS dji_sdk 源码分析|整体框架
DJI ROS dji_sdk 源码分析|整体框架launch文件CMakeLists.txtcpp文件main.cppOSDK 是一个用于开发无人机应用程序的开发工具包,基于OSDK 开发的应用程序能够运行在机载计算机上(如Manifold 2),开发者通过调用OSDK 中指定的接口能够…...

HT32合泰单片机开发环境搭建和配置教程
HT32合泰(Holtek)单片机开发环境搭建安装教程 前言 最近在准备合泰杯的比赛,在看合泰官方的PPT和数据手册学习,顺便做个合泰单片机的开发环境搭建教程。 合泰杯比赛发放的开发板是ESK32-30501,用的单片机是HT32F52352。 合泰杯官网地址&a…...

动态内存分配之伙伴算法
伙伴算法 伙伴算法是一种在计算机内存管理中使用的算法,用于分配和释放内存。它是一种基于二叉树的动态内存分配算法,可以高效地分配和合并内存块。伙伴算法是一种按照固定大小分配内存的算法,例如,每个内存块的大小为2的n次幂&a…...

CGAL 根据扫描线方向和角度对法向量进行重定向
目录一、算法原理1、主要函数二、代码实现一、算法原理 最小生成树对法向量定向的结果在具有许多尖锐特征和遮挡的机载点云数据中结果并不理想。scanline_orient_normals()是专门用于具有扫描线特性的点云法向量重定向的替代方法。它充分利用了某些激光雷达扫描器的LAS特性&…...

一个C#开发的开源的快速启动工具
更多开源项目请查看:一个专注推荐.Net开源项目的榜单 平常计算机安装软件比较多、或者工作涉及的文件比较多,很多人都会直接放在桌面,一方面不安全,还不容易查找,这时候我们往往,都会放在其他硬盘内&#x…...

Paddle项目调试记录
PaddlePaddle是百度公司提出的深度学习框架。近年来深度学习在很多机器学习领域都有着非常出色的表现,在图像识别、语音识别、自然语言处理、机器人、网络广告投放、医学自动诊断和金融等领域有着广泛应用。面对繁多的应用场景,深度学习框架有助于建模者…...

3月11日,30秒知全网,精选7个热点
///微盟集团宣布接入百度文心一言 据介绍,微盟SaaS产品和数字营销服务将与文心一言的技术能力实现深度融合,通过AIGC技术,深化微盟在营销AI创意内容生产、智能营销、智能客服、智能经营等方面的布局 ///T3出行与华为云深化业务合作 双方将在…...

C win32基础学习(四)
上一篇我们已经介绍了关于窗口处理函数的知识。本篇我们说一下注册窗口类,创建窗口和显示窗口的内容。 前文 窗口创建过程 定义WinMain函数 定义窗口处理函数(自定义,处理消息) 注册窗口类(向操作系统写入一些数据) 创建窗口&…...

Java 日期时间API(Java 8及以上)
Java 8及以上版本提供了新的日期时间API,其中包括了LocalDate、LocalTime、LocalDateTime、ZonedDateTime、Duration、Period等类,这些类提供了更加丰富和灵活的日期时间操作方法。 LocalDate LocalDate类表示一个本地日期,不包含时间和时区…...

DHCP的配置
实验目的熟悉DHCP的应用场景掌握DHCP的配置方法实验拓扑DHCP的配置如图15-2所示: 图15-2:DHCP的配置 实验步骤配置IP地址<Huawei>system-view Enter system view, return user view with Ctrl+Z....

JavaWeb14-线程池
目录 1.传统线程的缺点 2.线程池的定义 3.线程池的优点 4.线程池的创建/使用(2类7种) 4.1.通过Executors(执行器)自动创建(6种) ①Executors.newFixedThreadPool:创建⼀个固定⼤⼩的线程池…...

[qiankun+nuxt]子应用请求本地文件报错404
前言 目前公司的前端架构是qiankunnuxt做的微前端项目 问题说明 在子应用中,前端需要模拟一些数据,方便后期演示调整而不需要重新打包 所以将一些数据存储到了本地的json文件中,但是获取时报了404的错误,找不到该文件。 页面报错…...

【Qt网络编程】实现TCP协议通信
文章目录概要:本期主要讲解QT中对于TCP协议通信的实现。一、TCP协议二、Qt中TCP协议处理1.QTcpSocket2.QTcpServer三、Qt实现TCP通信1.客户端2.服务器端结尾概要:本期主要讲解QT中对于TCP协议通信的实现。 一、TCP协议 传输控制协议(TCP&am…...

Webpack打包———处理样式资源
基本使用 本质上,webpack 是一个用于现代 JavaScript 应用程序的 静态模块打包工具。当 webpack 处理应用程序时,它会在内部从一个或多个入口点构建一个 依赖图(dependency graph),然后将你项目中所需的每一个模块组合成一个或多个 bundles&a…...

VP记录:Codeforces Round 857 (Div. 2) A~D
传送门:CF A题 Likes: 这道题的题意很变态,十分的难懂,简直就是一坨shit,这场比赛最后被骂是有原因的 简单来说就是对于一个项目,每一个人都能对此加一或者减一,最后问你这个项目每一时刻最大和最小是多少.题目中只说明了只能点赞后才能取消,并没有解释存在取消操作必存在点…...

Docker常用项目实战演练
docker镜像源的修改 linux环境下编辑 /etc/docker/daemon.json vi /etc/docker/daemon.json #如添加如下网易镜像源 { "registry-mirrors": ["http://hub-mirror.c.163.com"] }docker run命令详细解释 日常工作中用的比较多的是docker run命令ÿ…...

Linux进程间通信-FIFO命名管道
Linux进程间通信-FIFO命名管道 1、概述 管道因为没有名称,所以只用于进程间的亲缘通信。为了克服这一缺点,提出了命名管道(FIFO),又称命名管道、FIFO文件。 FIFO不同于无名管道,它提供与之关联的路径名,该路径名以FIF…...

【Kafka】记录一次基于connect-mirror-maker做的Kafka集群迁移完整过程
文章目录背景环境工具选型实操MM1MM2以MM2集群运行以Standalone模式运行验证附录MM2配置表其他背景 一个测试环境的kafka集群,Topic有360,Partition有2000,部署在虚拟机上,由于多方面原因,要求迁移至k8s容器内&#x…...

实现VOC数据集与COCO数据集格式转换
实现VOC数据集与COCO数据集格式转换2、将voc数据集的xml转化为coco数据集的json格式2、COCO格式的json文件转化为VOC格式的xml文件3、将 txt 文件转换为 Pascal VOC 的 XML 格式<annotation><folder>文件夹目录</folder><filename>图片名.jpg</file…...

常用的密码算法有哪些?
我们将密码算法分为两大类。 对称密码(密钥密码)——算法只有一个密钥。如果多个参与者都知道该密钥,该密钥 也称为共享密钥。非对称密码(公钥密码)——参与者对密钥的可见性是非对称的。例如,一些参与者仅…...

SNS (Simple Notification Service)简介
SNS (Simple Notification Service) 是一种完全托管的发布/订阅消息收发和移动通知服务,用于协调向订阅终端节点和客户端的消息分发。 和SQS (Simple Queue Service)一样,SNS也可以轻松分离和扩展微服务,分布式系统和无服务应用程序…...

JVM初步理解浅析
一、JVM的位置 JVM的位置 JVM在操作系统的上一层,是运行在操作系统上的。JRE是运行环境,而JVM是包含在JRE中 二、JVM体系结构 垃圾回收主要在方法区和堆,所以”JVM调优“大部分也是发生在方法区和堆中 可以说调优就是发生在堆中…...

【巨人的肩膀】MySQL面试总结(一)
💪 目录💪1、什么是ER图2、数据库范式了解吗3、超键、候选键、主键、外键分别是什么?4、为什么不推荐使用外键与级联5、什么是存储过程6、drop、delete与truncate区别7、数据库设计通常分为那几步8、什么是关系型数据库9、什么是SQL10、MySQL…...

【数据结构之树】——什么是树,树的特点,树的相关概念和表示方法以及在实际的应用。
文章目录一、1.树是什么?2.树的特点二、树的相关概念三、树的表示方法1.常规方法表示树2.使用左孩子右兄弟表示法3. 使用顺序表来存储父亲节点的下标三、树在实际的应用总结一、1.树是什么? 树是一种非线性的数据结构,它是由n(n&…...