当前位置: 首页 > news >正文

这些Coding套路你不会还不知道吧?

对于一名程序员来说,编码进阶是成为优秀工程师非常重要的一步,它可以让我们更加熟练地掌握编程,深入理解数据结构和算法,从而更好地完成复杂的任务,提高工作效率。而我认为熟练使用设计模式就是编码进阶的最好方式之一,下面就用一篇文章来分享下Go开发中常用的设计模式。

  • 1️⃣全局单一实例:单例模式

  • 🚗获取对象超简单:工厂模式

  • 📋重复代码太多?试试:模板方法模式

  • 👻接口对应功能不知道怎么维护?这里有:策略模式

  • 🎈独特好玩的Functional Options模式

What?Why?

从两个问题开始今天的分享:

设计模式是什么?

简单来讲,就两个字:套路,编码的套路,在我们写代码的时候这个套路可以不用,但是不能不知道。

为什么要使用设计模式?

设计模式是一种被反复使用的,针对软件设计中常见问题的可复用解决方案。它们提供了一种经过验证的方式来解决复杂的设计问题,并帮助开发人员编写更加清晰、可维护和可扩展的代码

使用设计模式的好处包括:

  1. 提高代码的可读性和可维护性。通过使用设计模式,开发人员可以将复杂的问题分解成更小、更易于管理的部分,并且可以将这些部分组织成一致的、易于理解的代码结构。
  2. 提高代码的可重用性。设计模式提供了一种标准化的解决方案,可以让相同的功能代码在多个地方重复使用,从而避免了重复编写相同的代码,减少了开发时间和成本。
  3. 提高代码的灵活性和扩展性。设计模式允许开发人员在不改变现有代码的情况下,轻松地添加新的功能或修改现有的功能。

常见的设计模式实践

1 全局单一实例:单例模式

首先,单例模式一般用于以下业务场景:

(1)整个程序的运行中只允许有一个类的实例。

(2)创建对象时耗时过多或者耗资源过多,但又经常用到的。

(3)需要全局访问并保证线程安全的对象。

(4)需要保持状态的对象。

具体场景:

数据库连接对象。我们在具体的项目中往往每种数据库驱动只会使用它的一个实例,因此在这里我们就能够使用单例模式。

代码:

import "sync"type MysqlConn struct {Addr string
}var (mysqlConn *MysqlConnonce = sync.Once{}
)func GetMySQLConn() *MysqlConn {once.Do(func() {mysqlConn = &MysqlConn{Addr: "127.0.0.1"}})return mysqlConn
}

2 获取对象超简单:工厂模式

工厂模式通常应用于以下场景:

(1)当一个系统需要灵活地配置一组对象,并且需要动态地选择其中的一个时。

(2)当一个类需要频繁地创建和销毁时,可以使用工厂模式来提高性能。

具体场景:

简单来讲就是想要获取一个实例,但是这个实例的属性可能会随着参数的变化而具有不同的形态,还可以用数据库连接来举例,我们有多个服务器可以进行连接,但是每次只能连接一个,而且连接的时候可以填写自己的认证账密。

代码:

type DB struct {Addr, UserName, Passwd string
}func NewMysqlConn(addr, userName, passwd string) *DB {return &DB{Addr:     addr,UserName: userName,Passwd:   passwd,}
}

3 重复代码太多?试试:模板方法模式

模板方法模式通常应用于以下场景:

(1)当一个算法的步骤中有一部分是不变的,而另一部分是需要根据不同的条件进行变化时,可以使用模板方法模式来实现。

(2)当一个类的子类需要实现一个接口的不同版本时,可以使用模板方法模式来实现。

具体场景:

做水果酸奶,水果或其他食材是统一的抽象,而火龙果、芒果、饼干都是具体,因为不管用什么水果或食材来做,做法都是如出一辙的,所以做法也是一个抽象,这就好比一个模板,对,就是模版方法模式。

代码:

import ("fmt""testing"
)type MakeYogurtTemplate interface {CreateYogurt() //准备好酸奶CutFruit()     //切水果Merge()        //放在一起搅拌Optimize()     //调制味道Eating()       //开吃Do()
}type DragonFruit struct {
}func (d *DragonFruit) CreateYogurt() {fmt.Println("用鲜奶和乳酸菌发酵好酸奶")
}func (d *DragonFruit) CutFruit() {fmt.Println("把火龙果切成块块")
}func (d *DragonFruit) Merge() {fmt.Println("放在一起进行搅拌")
}func (d *DragonFruit) Optimize() {fmt.Println("调制出自己喜欢的味道")
}func (d *DragonFruit) Eating() {fmt.Println("开吃")
}func (d *DragonFruit) Do() {d.CreateYogurt()d.CutFruit()d.Merge()d.Optimize()d.Eating()
}func TestDragonFruit(t *testing.T) {d := &DragonFruit{}d.Do()
}type Mango struct {
}func (m *Mango) CreateYogurt() {fmt.Println("用鲜奶和乳酸菌发酵好酸奶")
}func (m *Mango) CutFruit() {fmt.Println("把芒果切成块块")
}func (m *Mango) Merge() {fmt.Println("放在一起进行搅拌")
}func (m *Mango) Optimize() {fmt.Println("调制出自己喜欢的味道")
}func (m *Mango) Eating() {fmt.Println("开吃")
}func (m *Mango) Do() {m.CreateYogurt()m.CutFruit()m.Merge()m.Optimize()m.Eating()
}func TestMango(t *testing.T) {m := &Mango{}m.Do()
}

4 接口对应功能不知道怎么维护?这里有:策略模式

策略模式通常在一个系统中需要多个算法,并且这些算法需要在不同的时间或条件下使用不同的算法时,可以使用策略模式来实现。

具体场景:

对于新手程序员同学经常会有这样的选择,到底是学Go还是学Java,这显然是两种不同的策略选择,但是不管是学习哪一个的基本流程都是差不多的,比如都是先准备学习资料,然后在学习和实践,因此可以基于此使用策略模式来形容。

代码:

策略抽象

type Learn interface {PrepareData()DoLearn()Play()
}func LearnLang(l Learn) {l.PrepareData()l.DoLearn()l.Play()
}

策略1

import "fmt"type LikeGo struct {
}func (g *LikeGo) PrepareData() {fmt.Println("准备Go资料")
}func (g *LikeGo) DoLearn() {fmt.Println("学习Go")
}func (g *LikeGo) Play() {fmt.Println("玩转Go语言")
}

策略2

import "fmt"type LikeJava struct {
}func (g *LikeJava) PrepareData() {fmt.Println("准备Java资料")
}func (g *LikeJava) DoLearn() {fmt.Println("学习Java")
}func (g *LikeJava) Play() {fmt.Println("玩Java")
}

执行策略

import "testing"func TestLearn(t *testing.T) {likeGo := &LikeGo{}LearnLang(likeGo)
}

5 独特好玩的Functional Options模式

Functional Options模式通常在当一个对象或函数具有多个参数时,这些参数可能会有不同的默认值或取值范围。通过将它们作为函数的选项传递,可以更灵活地控制函数的行为

具体场景:

gRPC服务进行实例化的时候有些参数可以不同填,即选填,之后在源码内部会使用默认的值,于是我们就可以使用以下的方式进行处理。

代码:

import "time"type RpcServer struct {Name    stringMaxConn intAddress []stringTimeOut time.Duration
}type RpcServerOption func(server *RpcServer)func WithName(name string) RpcServerOption {return func(server *RpcServer) {server.Name = name}
}func WithMaxConn(max int) RpcServerOption {return func(server *RpcServer) {server.MaxConn = max}
}func WithAddress(addr []string) RpcServerOption {return func(server *RpcServer) {server.Address = addr}
}func WithTimeOut(timeout time.Duration) RpcServerOption {return func(server *RpcServer) {server.TimeOut = timeout}
}func NewRpcServer(opts ...RpcServerOption) *RpcServer {server := &RpcServer{}for _, opt := range opts {opt(server)}return server
}

实例化:

import ("fmt""testing""time"
)func TestCreateRpcServerByOptions(t *testing.T) {rpcServer := NewRpcServer(WithAddress([]string{"127.0.0.1"}),WithName("rpcServer"),WithMaxConn(1),WithTimeOut(time.Second),)fmt.Println(*rpcServer)
}

小总结

本文主要介绍了Go开发中常用的设计模式,包括全局单一实例:单例模式、工厂模式、模板方法模式、策略模式和Functional Options模式。这些设计模式可以帮助我们更好地组织代码,提高代码的可读性和可重用性。

总之,掌握这些设计模式对于提高Go程序员的编码能力非常有帮助,可以让我们在编写代码时更加得心应手,同时也能提高代码的质量和可维护性。

相关文章:

这些Coding套路你不会还不知道吧?

对于一名程序员来说,编码进阶是成为优秀工程师非常重要的一步,它可以让我们更加熟练地掌握编程,深入理解数据结构和算法,从而更好地完成复杂的任务,提高工作效率。而我认为熟练使用设计模式就是编码进阶的最好方式之一…...

Spring Boot深度解析:快速开发的秘密

🌷🍁 博主猫头虎(🐅🐾)带您 Go to New World✨🍁 🦄 博客首页——🐅🐾猫头虎的博客🎐 🐳 《面试题大全专栏》 🦕 文章图文…...

mysql数据库备份(mysqldump)

mysqldump命令备份数据 mysqldump -u root -p --databases 数据库1 数据库2 > xxx.sqlmysqldump常用操作示例 1. 备份全部数据库的数据和结构 mysqldump -uroot -p123456 -A > /data/mysqlbackup/mydb.sql2. 备份全部数据库的结构(加 -d 参数) …...

linux Nginx+Tomcat负载均衡、动静分离

linux NginxTomcat负载均衡、动静分离 1、Tomcat的基本介绍1.1Tomcat是什么?1.2Tomcat的构成组件1.3Tomcat的核心功能1.4Tomcat请求过程 2、Tomcat部署2.1安装tomcat2.2优化tomcat启动速度2.4主要目录说明 3、Tomcat 虚拟主机配置3.1创建fsj和mws项目目录和文件3.2修…...

ts 枚举类型原理及其应用详解

ts 枚举类型介绍 TypeScript的枚举类型是一种特殊的数据类型,它允许开发者为一组相关值定义一个共同的名称,使我们可以更清晰、更一致地使用这些值。 枚举类型在TypeScript中用enum关键字定义,每个枚举值默认都是数字类型,从0开…...

腾讯mini项目-【指标监控服务重构】2023-08-23

今日已办 进度和问题汇总 请求合并 feature/venus tracefeature/venus metricfeature/profile-otel-baserunner-stylebugfix/profile-logger-Syncfeature/profile_otelclient_enable_config 完成otel 开关 trace-采样metrice-reader 已经都在各自服务器运行,并接入…...

C- ssize_t size_t

size_t 和 ssize_t 都是在 C 和 C 的标准库中定义的数据类型,它们通常用于表示大小和长度。然而,它们有关键的区别。 size_t: 定义:size_t 是一个无符号整数类型,它是适合表示对象的大小的类型。在 POSIX 中,它也用于…...

ubuntu20.04 Supervisor 开机自启动脚本一文配置

前言: 最近发现一种非常好的开机启动服务方式,不光可以开机自启动,而且还可以进行开机节点的进程守护,这样大大确保了线程的稳定情况,这种服务甚至可以守护开机的进程,所以比之前设置 rc.local 开机自启动脚本一文配置节点好出很多,它甚至可以使用网页登录监管我开机自启…...

【面试刷题】——函数指针和指针函数

“函数指针”(function pointer)和 “指针函数”(pointer to function)是两个不同的概念,它们涉及到指针和函数的结合使用。 函数指针(Function Pointer): 函数指针是指向函数的指…...

目标分类笔记(一): 利用包含多个网络多种训练策略的框架来完成多目标分类任务(从数据准备到训练测试部署的完整流程)

目标分类 一、目标分类介绍1.1 二分类和多分类的区别1.2 单标签和多标签输出的区别 二、代码获取三、数据集准备四、环境搭建4.1 环境测试 五、模型训练六、模型测试6.1 多标签训练-单标签输出结果6.2 多标签训练-多标签输出结果 一、目标分类介绍 目标分类是一种监督学习任务…...

【100天精通Python】Day61:Python 数据分析_Pandas可视化功能:绘制饼图,箱线图,散点图,散点图矩阵,热力图,面积图等(示例+代码)

目录 1 Pandas 可视化功能 2 Pandas绘图实例 2.1 绘制线图 2.2 绘制柱状图 2.3 绘制随机散点图 2.4 绘制饼图 2.5 绘制箱线图A 2.6 绘制箱线图B 2.7 绘制散点图矩阵 2.8 绘制面积图 2.9 绘制热力图 2.10 绘制核密度估计图 1 Pandas 可视化功能 pandas是一个强大的数…...

2023华为产品测评官-开发者之声 | 华为云CodeArts征文活动,多重好礼邀您发声!

"2023华为产品测评官-开发者之声"活动激发了众多开发者和技术爱好者的热情,他们纷纷递交了精心编写的产品测评报告。活动社群充满活力,参与者们热衷于交流讨论,互相帮助解决问题,一起探索云技术的无限可能。…...

Python 图形化界面基础篇:获取文本框中的用户输入

Python 图形化界面基础篇:获取文本框中的用户输入 引言 Tkinter 库简介步骤1:导入 Tkinter 模块步骤2:创建 Tkinter 窗口步骤3:创建文本框步骤4:获取文本框中的用户输入步骤5:启动 Tkinter 主事件循环 完整…...

【驱动开发】实现三盏灯的控制,编写应用程序测试

head.h #ifndef __HEAD_H__ #define __HEAD_H__//LED1:PE10 //LED2:PF10 //LED3:PE8#define LED_RCC 0X50000A28 //使能GPIO#define LED_MODER 0X50006000 //设置输出模式 #define LED_ODR 0X50006014 //设置输出高低电平#define LED2_MODER 0X50007000 …...

Vue3+ElementUI使用

<!DOCTYPE html> <html> <head><meta charset"UTF-8"><meta name"viewport" content"initial-scale1.0,maximum-scale1.0,minimum-scale1.0,user-scalable0, widthdevice-width"/><!-- 引入样式 --><lin…...

MySQL 和 MariaDB 版本管理的历史背景及差异

目录 MariaDB MySQL 差异 关于 SQLE SQLE 获取 ​ 了解更多 需要说明的是 MySQL 和 MariaDB 都有社区版和企业版。对于 MySQL&#xff0c;这两个版本都是由同一家公司&#xff08;Oracle&#xff09;提供&#xff0c;遵循相同的版本编号体系&#xff0c;企业版包含更丰富…...

linux驱动开发--day4(字符设备驱动注册内部流程、及实现备文件和设备的绑定下LED灯实验)

一、字符设备驱动注册的内部过程 1.分配struct cdev对象空间 2.初始化struct cdev对象 3.注册cdev对象 二、注册字符设备驱动分步实现 1.分配字符设备驱动对象 2.字符设备驱动对象初始化 3.设备号的申请 4.根据申请的设备号和驱动对象注册驱动 三、open函数回调驱动中…...

elasticsearch5-RestAPI操作

个人名片&#xff1a; 博主&#xff1a;酒徒ᝰ. 个人简介&#xff1a;沉醉在酒中&#xff0c;借着一股酒劲&#xff0c;去拼搏一个未来。 本篇励志&#xff1a;三人行&#xff0c;必有我师焉。 本项目基于B站黑马程序员Java《SpringCloud微服务技术栈》&#xff0c;SpringCloud…...

数据结构与算法(一)

文章目录 数据结构与算法(一)1 位运算、算法是什么、简单排序1.1 实现打印一个整数的二进制1.2 给定一个参数N,返回1!+2!+3!+4!+...+N!的结果1.3 简单排序算法2 数据结构大分类、前缀和、对数器2.1 实现前缀和数组2.2 如何用1\~5的随机函数加工出1\~7的随机函数2.3 如何把不…...

Matlab--微积分问题的计算机求解

目录 1.单变量函数的极限问题 1.1.公式例子 1.2.对应例题 1 2.多变量函数的极限问题 3.函数导数的解析解 4.多元函数的偏导数 5.Jacobian函数 6.Hessian矩阵 7.隐函数的偏导 8.不定积分问题的求解 9.定积分的求解问题 10. 多重积分的问题求解 1.单变量函数的极限问题 …...

SpringBoot-17-MyBatis动态SQL标签之常用标签

文章目录 1 代码1.1 实体User.java1.2 接口UserMapper.java1.3 映射UserMapper.xml1.3.1 标签if1.3.2 标签if和where1.3.3 标签choose和when和otherwise1.4 UserController.java2 常用动态SQL标签2.1 标签set2.1.1 UserMapper.java2.1.2 UserMapper.xml2.1.3 UserController.ja…...

ESP32 I2S音频总线学习笔记(四): INMP441采集音频并实时播放

简介 前面两期文章我们介绍了I2S的读取和写入&#xff0c;一个是通过INMP441麦克风模块采集音频&#xff0c;一个是通过PCM5102A模块播放音频&#xff0c;那如果我们将两者结合起来&#xff0c;将麦克风采集到的音频通过PCM5102A播放&#xff0c;是不是就可以做一个扩音器了呢…...

【算法训练营Day07】字符串part1

文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接&#xff1a;344. 反转字符串 双指针法&#xff0c;两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

IP如何挑?2025年海外专线IP如何购买?

你花了时间和预算买了IP&#xff0c;结果IP质量不佳&#xff0c;项目效率低下不说&#xff0c;还可能带来莫名的网络问题&#xff0c;是不是太闹心了&#xff1f;尤其是在面对海外专线IP时&#xff0c;到底怎么才能买到适合自己的呢&#xff1f;所以&#xff0c;挑IP绝对是个技…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

HubSpot推出与ChatGPT的深度集成引发兴奋与担忧

上周三&#xff0c;HubSpot宣布已构建与ChatGPT的深度集成&#xff0c;这一消息在HubSpot用户和营销技术观察者中引发了极大的兴奋&#xff0c;但同时也存在一些关于数据安全的担忧。 许多网络声音声称&#xff0c;这对SaaS应用程序和人工智能而言是一场范式转变。 但向任何技…...

【C++】纯虚函数类外可以写实现吗?

1. 答案 先说答案&#xff0c;可以。 2.代码测试 .h头文件 #include <iostream> #include <string>// 抽象基类 class AbstractBase { public:AbstractBase() default;virtual ~AbstractBase() default; // 默认析构函数public:virtual int PureVirtualFunct…...