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

Golang单例模式学习笔记

前言

单例模式是常用的一种设计模式,一般用于比如客户端、连接的创建等,防止创建多个导致性能消耗。所以我认为单例模式的核心,就是“防止重复”。本文将在Golang中进行单例模式的实现。

实现

版本1——检测-创建

最基础的版本,就是依照“防止重复”来实现。代码如下:

package maintype Test1 struct {
}var t1 *Test1func main() {}func NewT1() *Test1 {if t1 == nil {t1 = &Test1{}}return t1
}

可见,只是在创建前,进行了一个判定,如果为空 再创建。不为空则直接返回。

但是这样版本存在有问题——即线程不安全。比如多个goroutine中同时运行其去创建,那么就很容易导致创建重复。

对此,解决方案也很简单——加锁即可。

版本2——加锁-检测-创建

很简单粗暴的加个锁——这样就能保证只有一个去进行检测、创建。规避了问题。

var mutex sync.Mutexfunc NewT1() *Test1 {mutex.Lock()defer mutex.Unlock()if t1 == nil {t1 = &Test1{}}return t1
}

但是这样带来了新的问题:频繁的加锁、删锁,带来了巨大的性能损耗。诸如t1已经存在的情况,本该直接返回即可,但是却需要白白加锁一次。

版本3——检测-加锁-检测-创建

即所说的Check-Lock-Check模式。代码如下:


func NewT1() *Test1 {if t1 == nil {mutex.Lock()defer mutex.Unlock()if t1 == nil {t1 = &Test1{}}}return t1
}

可以看到,就是在最开始的lock之前,进行一次检测。一个if判断的消耗还是很小的,如果存在再进入加锁创建的流程。

在Golang中,可以使用sync/atomic这个包,原子化的加载一个标志,来实现这套判断。
即:

import "sync"
import "sync/atomic"var initialized uint32
... // 此处省略func GetInstance() *singleton {if atomic.LoadUInt32(&initialized) == 1 {  // 原子操作 return instance}mu.Lock()defer mu.Unlock()if initialized == 0 {instance = &singleton{}atomic.StoreUint32(&initialized, 1)}return instance
}
//此代码直接复制至原文——https://www.liwenzhou.com/posts/Go/singleton/

版本4——Golang常用的方式

饿汉和懒汉式

饿汉

饿汉模式,即像一个饿肚子人一样迫不及待的去享用美食。即 在程序加载的时候就创建并实例化,因此也无需考虑并发等情况。

示例:

package mainimport "fmt"type Singleton struct {// 在这里定义单例对象的属性
}var instance *Singleton = createInstance()func createInstance() *Singleton {// 在这里创建并初始化单例对象return &Singleton{// 初始化单例对象的属性}
}func GetInstance() *Singleton {return instance
}func main() {// 使用单例模式获取实例singletonInstance := GetInstance()// 使用单例实例fmt.Println(singletonInstance)
}
//此代码复制自原文——https://i6448038.github.io/2023/12/16/singleton/

懒汉

顾名思义,懒得管…等用到时候再创建。此时程序已经启动并正在运行,此时创建实例可能会出现多线程的情况,所以要考虑并发问题。

上述的实现代码便是懒汉模式。

参考资料

https://www.liwenzhou.com/posts/Go/singleton/

https://i6448038.github.io/2023/12/16/singleton/

相关文章:

Golang单例模式学习笔记

前言 单例模式是常用的一种设计模式,一般用于比如客户端、连接的创建等,防止创建多个导致性能消耗。所以我认为单例模式的核心,就是“防止重复”。本文将在Golang中进行单例模式的实现。 实现 版本1——检测-创建 最基础的版本&#xff0…...

Leetcode HOT150

55. 跳跃游戏 给你一个非负整数数组 nums ,你最初位于数组的 第一个下标 。数组中的每个元素代表你在该位置可以跳跃的最大长度。 判断你是否能够到达最后一个下标,如果可以,返回 true ;否则,返回 false 。 示例 1 …...

仿牛客项目Day1

SpringMVC 架构 spring的前端控制器是DispatcherServlet 模板引擎Thymeleaf 这个还不知道干嘛的 mvc演示 get请求 RequestMapping:声明访问路径和http方法get或set什么的 ResponseBody:java对象转为json格式的数据,表示该方法的返回结…...

Effective C++ 学习笔记 条款17 以独立语句将newed对象置入智能指针

假设我们有个函数用来揭示处理程序的优先权&#xff0c;另一个函数用来在某动态分配所得的Widget上进行某些带有优先权的处理&#xff1a; int priority();void processWidget(std::st1::shared_ptr<Widget> pw, int priority);由于谨记“以对象管理资源”&#xff08;条…...

通过Electron打包前端项目为exe

&#x1f9d1;‍&#x1f393; 个人主页&#xff1a;爱蹦跶的大A阿 &#x1f525;当前正在更新专栏&#xff1a;《JavaScript保姆级教程》、《VUE》、《Krpano》 ✨ 正文 1、 拉取electron官网上的demo&#xff0c;拉下来之后安装依赖&#xff0c;项目跑起来之后&#xff0c;就…...

大模型时代企业知识全生命周期管理解决方案

©作者|Zhongmei 来源|神州问学 摘 要 越来越多的企业开始意识到数据的重要性。同时意识到&#xff0c;企业想保持长远的发展&#xff0c;还需要协调组织协作、利用现有的数据沉淀经验知识、累积数据资产。据IDC调查&#xff0c;目前企业结构化数据仅占到全部数据量的20%…...

C#冒泡排序算法

冒泡排序实现原理 冒泡排序是一种简单的排序算法&#xff0c;其原理如下&#xff1a; 从待排序的数组的第一个元素开始&#xff0c;依次比较相邻的两个元素。 如果前面的元素大于后面的元素&#xff08;升序排序&#xff09;&#xff0c;则交换这两个元素的位置&#xff0c;使…...

【前端寻宝之路】总结学习使用CSS的引入方式

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法|MySQL| ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” #mermaid-svg-BNJBIEvpN0GHNeJ1 {font-family:"trebuchet ms",verdana,arial,sans-serif;f…...

Python中输入输出函数input和print用法

# 读入一个字符串 s input() print(s)abcdef abcdef# 读入一个整数 n int(input()) print(n)5 5# 读入两个整数(空格间隔) # input()表示读入一行字符串 # split()表示以空格间隔切分出多个字符串序列&#xff0c;如果逗号间隔可以加参数split(,) # map()将序列每个元素转为整…...

简单认识Linux

今天带大家简单认识一下Linux&#xff0c;它和我们日常用的Windows有什么不同呢&#xff1f; Linux介绍 Linux内核&发行版 Linux内核版本 内核(kernel)是系统的心脏&#xff0c;是运行程序和管理像磁盘和打印机等硬件设备的核心程序&#xff0c;它提供了一个在裸设备与…...

javascript正则深入

文章目录 一、前言二、高级`API`2.1、模式匹配的用法`(x)`2.2、非捕获括号的模式匹配`(?:x)`2.3、先行断言`x(?=y)`2.4、后行断言`(?<=y)x`2.5、正向否定查找`x(?!y)`2.6、反向否定查找`(?<!y)x`2.7、字符集合和反向字符集合的用法 `[xyz] / [^xyz]`2.8、词边界和非…...

React-封装自定义Hook

1.声明函数 说明&#xff1a;声明一个以use打头的函数 function useToggle(){} 2.封装 说明&#xff1a;在函数体内封装可复用的逻辑 const [value,setValue]useState(true)const toggle()>{setValue(!value)} 3.返回 说明&#xff1a;把组件中用到的状态或者回调retu…...

Spark实战-基于Spark日志清洗与数据统计以及Zeppelin使用

Saprk-日志实战 一、用户行为日志 1.概念 用户每次访问网站时所有的行为日志(访问、浏览、搜索、点击)用户行为轨迹&#xff0c;流量日志2.原因 分析日志&#xff1a;网站页面访问量网站的粘性推荐3.生产渠道 (1)Nginx(2)Ajax4.日志内容 日志数据内容&#xff1a;1.访问的…...

Springboot中Redis的配置使用

新建 向pom.xml中添加依赖&#xff0c;这个可以不用标注版本号 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency> 配置yml文件&#xff08;文件名不可以错…...

【node版本问题】运行项目报错 PostCSS received undefined instead of CSS string

最近该项目没有做任何修改&#xff0c;今天运行突然跑不起来报错了 PostCSS received undefined instead of CSS string 【原因】突然想起来期间有换过 node 版本为 16.17.1 【解决】将 node 版本换回之前的 14.18.0 就可以了...

Spring揭秘:BeanDefinitionRegistry应用场景及实现原理!

内容概要 BeanDefinitionRegistry接口提供了灵活且强大的Bean定义管理能力&#xff0c;通过该接口&#xff0c;开发者可以动态地注册、检索和移除Bean定义&#xff0c;使得Spring容器在应对复杂应用场景时更加游刃有余&#xff0c;增强了Spring容器的可扩展性和动态性&#xf…...

蓝桥杯(3.5)

789. 数的范围 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int q sc.nextInt();int[] res new int[n];for(int i0;i<n;i)res[i] sc.nextInt();while(q-- ! 0) {int…...

434G数据失窃!亚信安全发布《勒索家族和勒索事件监控报告》

最新态势快速感知 最新一周全球共监测到勒索事件90起&#xff0c;与上周相比数量有所增加。 lockbit3.0仍然是影响最严重的勒索家族&#xff1b;alphv和cactus恶意家族也是两个活动频繁的恶意家族&#xff0c;需要注意防范。 Change Healthcare - Optum - UnitedHealth遭受了…...

7-18 彩虹瓶(Python)

彩虹瓶的制作过程&#xff08;并不&#xff09;是这样的&#xff1a;先把一大批空瓶铺放在装填场地上&#xff0c;然后按照一定的顺序将每种颜色的小球均匀撒到这批瓶子里。 假设彩虹瓶里要按顺序装 N 种颜色的小球&#xff08;不妨将顺序就编号为 1 到 N&#xff09;。现在工…...

php使用ElasticSearch

ElasticSearch简介 Elasticsearch 是一个分布式的、开源的搜索分析引擎&#xff0c;支持各种数据类型&#xff0c;包括文本、数字、地理、结构化、非结构化。 Lucene与ElasticSearch Apache Lucene是一款高性能的、可扩展的信息检索&#xff08;IR&#xff09;工具库&#xf…...

浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)

✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义&#xff08;Task Definition&…...

华为云AI开发平台ModelArts

华为云ModelArts&#xff1a;重塑AI开发流程的“智能引擎”与“创新加速器”&#xff01; 在人工智能浪潮席卷全球的2025年&#xff0c;企业拥抱AI的意愿空前高涨&#xff0c;但技术门槛高、流程复杂、资源投入巨大的现实&#xff0c;却让许多创新构想止步于实验室。数据科学家…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

Java如何权衡是使用无序的数组还是有序的数组

在 Java 中,选择有序数组还是无序数组取决于具体场景的性能需求与操作特点。以下是关键权衡因素及决策指南: ⚖️ 核心权衡维度 维度有序数组无序数组查询性能二分查找 O(log n) ✅线性扫描 O(n) ❌插入/删除需移位维护顺序 O(n) ❌直接操作尾部 O(1) ✅内存开销与无序数组相…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路

进入2025年以来&#xff0c;尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断&#xff0c;但全球市场热度依然高涨&#xff0c;入局者持续增加。 以国内市场为例&#xff0c;天眼查专业版数据显示&#xff0c;截至5月底&#xff0c;我国现存在业、存续状态的机器人相关企…...

pam_env.so模块配置解析

在PAM&#xff08;Pluggable Authentication Modules&#xff09;配置中&#xff0c; /etc/pam.d/su 文件相关配置含义如下&#xff1a; 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块&#xff0c;负责验证用户身份&am…...

如何将联系人从 iPhone 转移到 Android

从 iPhone 换到 Android 手机时&#xff0c;你可能需要保留重要的数据&#xff0c;例如通讯录。好在&#xff0c;将通讯录从 iPhone 转移到 Android 手机非常简单&#xff0c;你可以从本文中学习 6 种可靠的方法&#xff0c;确保随时保持连接&#xff0c;不错过任何信息。 第 1…...

uniapp微信小程序视频实时流+pc端预览方案

方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度​WebSocket图片帧​定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐​RTMP推流​TRTC/即构SDK推流❌ 付费方案 &#xff08;部分有免费额度&#x…...

unix/linux,sudo,其发展历程详细时间线、由来、历史背景

sudo 的诞生和演化,本身就是一部 Unix/Linux 系统管理哲学变迁的微缩史。来,让我们拨开时间的迷雾,一同探寻 sudo 那波澜壮阔(也颇为实用主义)的发展历程。 历史背景:su的时代与困境 ( 20 世纪 70 年代 - 80 年代初) 在 sudo 出现之前,Unix 系统管理员和需要特权操作的…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)

目录 一、&#x1f44b;&#x1f3fb;前言 二、&#x1f608;sinx波动的基本原理 三、&#x1f608;波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、&#x1f30a;波动优化…...