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

Golang学习笔记_27——单例模式

Golang学习笔记_24——泛型
Golang学习笔记_25——协程Golang学习笔记_25——协程
Golang学习笔记_26——通道


文章目录

    • 单例模式
      • 1. 介绍
      • 2. 应用场景
      • 3. 实现
        • 3.1 饿汉式
        • 3.2 懒汉模式
    • 源码


单例模式

1. 介绍

单例模式是一种创建型设计模式,它确保一个类只有一个实例,并提供一个全局访问点来访问这个实例。

这种模式在很多场景下非常有用,比如数据库连接池、日志系统等,这些场景中我们通常希望在整个应用程序中只有一个对象来负责相关的操作,避免资源的浪费和数据的不一致

2. 应用场景

  • 数据库连接池:在应用程序中,数据库连接的创建和销毁是比较消耗资源的操作。使用单例模式可以确保整个应用程序只有一个数据库连接池实例,多个地方需要获取数据库连接时都从这个连接池中获取,这样可以有效地管理数据库连接,提高性能并节省资源。
  • 日志系统:一个应用程序通常只需要一个日志记录器来统一记录各种操作信息。单例模式可以保证整个系统只有一个日志记录器实例,所有的日志记录操作都通过这个实例来完成,方便对日志进行统一管理和配置。
  • 配置管理:对于应用程序的配置信息,如服务器端口号、数据库连接参数等,使用单例模式可以确保整个应用程序只有一个配置管理实例,这样可以方便地在不同的模块中获取和修改配置信息,并且保证配置信息的一致性。

3. 实现

3.1 饿汉式
type Singleton struct{}var singleInstance *Singleton = &Singleton{}func GetInstance() *Singleton {return singleInstance
}func test1() {instance1 := GetInstance()instance2 := GetInstance()fmt.Println(instance1 == instance2)
}

说明
这种方式在程序启动时就初始化了单例实例singleInstance。&Singleton{}创建了一个Singleton结构体的实例,并将其赋值给singleInstance。

GetInstance函数只是简单地返回这个已经初始化好的实例。这种方式被称为饿汉式,因为实例是在程序开始时就 “急切” 地创建好了,而不管是否马上会被用到。

优点是实现简单,并且在多线程环境下也是安全的,因为实例在任何线程访问之前就已经创建好了。

缺点是如果单例的初始化过程很复杂或者资源消耗大,可能会导致程序启动变慢。

3.2 懒汉模式

线程不安全


type Singleton struct{}var singleInstance *Singleton
// 懒汉式(非线程安全)
func GetInstance2() *Singleton {fmt.Println("GetInstance2")if singleInstance == nil {singleInstance = &Singleton{}}return singleInstance
}func test1() {
instance1 := GetInstance()
instance2 := GetInstance()
fmt.Println(instance1 == instance2)
}

懒汉式单例模式。在GetInstance函数中,首先检查singleInstance是否为nil。如果是,就创建一个Singleton结构体的新实例并赋值给singleInstance,然后返回这个实例

线程安全

type Singleton struct{}var singleInstance *Singleton// 懒汉式(线程安全)
var mutex sync.Mutexfunc GetInstance3() *Singleton {fmt.Println("GetInstance3")mutex.Lock()defer mutex.Unlock()if singleInstance == nil {singleInstance = &Singleton{}}return singleInstance
}func test1() {
instance1 := GetInstance()
instance2 := GetInstance()
fmt.Println(instance1 == instance2)
}

为了在多线程环境下正确地实现懒汉式单例模式,引入了互斥锁sync.Mutex

在GetInstance函数中,首先调用mutex.Lock()获取锁,这确保了同一时刻只有一个线程能够进入临界区

使用defer mutex.Unlock()可以保证在函数返回之前释放锁。这样,即使多个线程同时调用GetInstance函数,也能保证只有一个线程会创建singleInstance实例,从而保证了单例模式的正确性。

type Singleton struct{}var singleInstance *Singletonvar once sync.Oncefunc GetInstance4() *Singleton {fmt.Println("GetInstance4")once.Do(func() {fmt.Println("just once!")singleInstance = &Singleton{}})return singleInstance
}func test1() {
instance1 := GetInstance()
instance2 := GetInstance()
fmt.Println(instance1 == instance2)
}

once.Do 方法会确保传入的匿名函数只会被执行一次

源码

package singletonimport ("fmt""sync"
)type Singleton struct{}// 饿汉式
// var singleInstance *Singleton = &Singleton{} // 懒汉式直接在程序运行时创建
func GetInstance1() *Singleton {fmt.Println("GetInstance1")return singleInstance
}var singleInstance *Singleton// 懒汉式(非线程安全)
func GetInstance2() *Singleton {fmt.Println("GetInstance2")if singleInstance == nil {singleInstance = &Singleton{}}return singleInstance
}// 懒汉式(线程安全)
var mutex sync.Mutexfunc GetInstance3() *Singleton {fmt.Println("GetInstance3")mutex.Lock()defer mutex.Unlock()if singleInstance == nil {singleInstance = &Singleton{}}return singleInstance
}// 使用sync.Once实现
var once sync.Oncefunc GetInstance4() *Singleton {fmt.Println("GetInstance4")once.Do(func() {fmt.Println("just once!")singleInstance = &Singleton{}})return singleInstance
}// 测试方法
func test1() {//instance1 := GetInstance1()//instance2 := GetInstance1()//instance1 := GetInstance2()//instance2 := GetInstance2()//instance1 := GetInstance3()//instance2 := GetInstance3()instance1 := GetInstance4()instance2 := GetInstance4()fmt.Println(instance1 == instance2)
}

相关文章:

Golang学习笔记_27——单例模式

Golang学习笔记_24——泛型 Golang学习笔记_25——协程Golang学习笔记_25——协程 Golang学习笔记_26——通道 文章目录 单例模式1. 介绍2. 应用场景3. 实现3.1 饿汉式3.2 懒汉模式 源码 单例模式 1. 介绍 单例模式是一种创建型设计模式,它确保一个类只有一个实例…...

хорошо哈拉少wordpress俄语主题

хорошо哈拉少wordpress俄语主题 wordpress俄文网站模板,推荐做俄罗斯市场的外贸公司建俄语独立站使用。 演示 https://www.jianzhanpress.com/?p7360...

[数据结构与算法]js实现二叉树

DFS 与 BFS dfs 递归 本质通过栈结构 bfs 层序遍历 通过队列结构 function permute(nums) {let res [];let cur []; // 记录当前内容let visted {}; //记录访问过的节点let len nums.length;function dfs(nth) {//递归终止条件if (nth len) {res.push([...cur]);return …...

MySQL程序之:连接到服务器的命令选项

本节介绍大多数MySQL客户端程序支持的选项,这些选项控制客户端程序如何建立与服务器的连接、连接是否加密以及连接是否压缩。这些选项可以在命令行或选项文件中给出。 连接建立的命令选项 本节介绍控制客户端程序如何建立与服务器的连接的选项。 表6.4连接建立选…...

python3GUI--仿崩坏三二次元登录页面(附下载地址) By:PyQt5

文章目录 一.前言二.预览三.实现方案1.实现原理1.PyQt52. 具体实现 2.UI设计1.UI组件化、模块化2.UI设计风格思路 3.项目代码结构4.使用方法3.代码分享1.支持跳转网页的QLabel组件2.三角形ICON按钮 四.总结 大小:33.3 …...

阿里云 Serverless 助力盟主直播:高并发下的稳定性和成本优化

在直播场景中,阿里云 Serverless 应用引擎 SAE 提供的无缝弹性伸缩与极速部署能力,确保直播间高并发时的流畅体验,降低了我们的运营成本,简化了运维流程。结合阿里云云原生数据库 PolarDB 的 Serverless 能力,实现了数…...

Unity 学习指南与资料分享

Unity学习资料 Unity学习资料 Unity学习资料 Unity 作为一款强大的跨平台游戏开发引擎,在游戏开发及实时 3D 内容创作领域占据着重要地位。它功能丰富、易于上手,支持多平台发布,为开发者提供了广阔的创作空间。下面为你带来全面的 Unity 学…...

Android SystemUI——CarSystemBar视图解析(十一)

前面文章我们已经把 CarSystemBar 从启动到构建视图,再到将视图添加到 Window 的流程分析完毕,我们知道默认情况下在车载系统中只显示顶部栏和底部栏视图的。这里我们在前面文章的基础上以顶部栏为例具体解析其视图的结构。 一、顶部栏解析 通过《CarSystemBar车载状态栏》这…...

.NET周刊【1月第1期 2025-01-05】

国内文章 3款.NET开源、功能强大的通讯调试工具,效率提升利器! https://www.cnblogs.com/Can-daydayup/p/18631410 本文介绍了三款功能强大的.NET开源通讯调试工具,旨在提高调试效率。这些工具包括LLCOM,提供串口调试和自动化处…...

初识go语言之指针用法

一、环境准备 安装go语言编译环境,官网地址:https://go.dev/dl/ 或者 https://golang.google.cn/dl/ 点击下载按提示安装即可 vscode 安装go语言扩展 测试 package mainimport "fmt"func main() {fmt.Println("Hello, World!") …...

用户中心项目教程(二)---umi3的使用出现的错误

目录 1.情况的说明 2.遇到的问题 1)第一个问题-关于npx的使用 2)第二个问题--unsupport问题 3)第三个收获--nodejs安装问题 4)第四个收获---nvm下载问题 5)第五个问题--尚未解决的问题 3.个人总结 1.情况的说明…...

Android设备:Linux远程gdb调试

更多内容:XiaoJ的知识星球 目录 1.准备工作1)安装Android NDK:2)连接Android手机3)编译程序 2.启动gdbserver1)**推送gdbserver及可执行文件**:**2)启动gdbserver**:3&am…...

(十四)WebGL纹理坐标初识

纹理坐标是 WebGL 中将 2D 图像(纹理)应用到 3D 物体表面的重要概念。在 WebGL 中,纹理坐标通常使用一个二维坐标系,称为 uv 坐标,它们决定了纹理图像如何映射到几何体上。理解纹理坐标的核心就是明白它们如何将二维纹…...

【机器学习】制造业转型:机器学习如何推动工业 4.0 的深度发展

我的个人主页 我的领域:人工智能篇,希望能帮助到大家!!!👍点赞 收藏❤ 引言 在当今科技飞速发展的时代,制造业正经历着前所未有的变革,工业4.0的浪潮席卷而来。工业4.0旨在通过将…...

Nginx安装配置Mac使用Nginx访问前端打包项目

目录 Linux安装环境变量配置 WinMac安装基本配置 Mac使用Nginx访问前端项目常用命令 Linux 官网:https://nginx.org/ 中文官网:https://nginx.p2hp.com/ 安装 http://nginx.org/en/download.html 1). 安装依赖包 由于nginx是基于c语言开发的&#x…...

国自然面上项目|基于组合机器学习算法的病理性近视眼底多模态影像资料自动化定量分析研究|基金申请·25-01-18

小罗碎碎念 今天和大家分享一个面上项目,资助年限为2020~2023,直接费用为55万。 病理性近视致盲问题严峻,机制和诊疗策略尚待探索。本项目基于前期积累的大量影像资料和算法开发工作,计划构建标准影像数据库&#xff0…...

03_UI自适应

因为Canvas大小是始终和屏幕一致的 所以设置Canvas的屏幕大小 通常设置为1920 * 1080 又因为屏幕的图像及按钮如果想适配各种显示屏需要锁定长或者宽, 之后利用钉子将其他图像利用创建空节点定在左右或者上下两侧 比如unity编辑器通常是锁定宽的,那我…...

Python在DevOps中的应用:自动化CI/CD管道的实现

《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 解锁Python编程的无限可能:《奇妙的Python》带你漫游代码世界 在现代软件开发中,DevOps理念的引入极大地提升了开发与运维的协作效率,而持续集成&#xff08…...

API接口技术推动电商数据处理的自动化

在当今数字化浪潮中,电商行业正以前所未有的速度发展。API(Application Programming Interface,应用程序编程接口)接口技术在这一过程中扮演着至关重要的角色。API接口作为连接不同系统和服务的关键桥梁,通过其自动化处…...

Nginx反向代理架构介绍

Nginx反向代理架构是一种强大的服务器架构模式,它位于用户和原始服务器之间,接收用户的请求并将其转发到一个或多个后端服务器,然后将从后端服务器获取的响应返回给用户,就好像这些内容都是由代理服务器本身直接提供的一样。以下是…...

ubuntu搭建nfs服务centos挂载访问

在Ubuntu上设置NFS服务器 在Ubuntu上,你可以使用apt包管理器来安装NFS服务器。打开终端并运行: sudo apt update sudo apt install nfs-kernel-server创建共享目录 创建一个目录用于共享,例如/shared: sudo mkdir /shared sud…...

ssc377d修改flash分区大小

1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...

聊聊 Pulsar:Producer 源码解析

一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

微信小程序 - 手机震动

一、界面 <button type"primary" bindtap"shortVibrate">短震动</button> <button type"primary" bindtap"longVibrate">长震动</button> 二、js逻辑代码 注&#xff1a;文档 https://developers.weixin.qq…...

【git】把本地更改提交远程新分支feature_g

创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...

Java求职者面试指南:Spring、Spring Boot、MyBatis框架与计算机基础问题解析

Java求职者面试指南&#xff1a;Spring、Spring Boot、MyBatis框架与计算机基础问题解析 一、第一轮提问&#xff08;基础概念问题&#xff09; 1. 请解释Spring框架的核心容器是什么&#xff1f;它在Spring中起到什么作用&#xff1f; Spring框架的核心容器是IoC容器&#…...

基于 TAPD 进行项目管理

起因 自己写了个小工具&#xff0c;仓库用的Github。之前在用markdown进行需求管理&#xff0c;现在随着功能的增加&#xff0c;感觉有点难以管理了&#xff0c;所以用TAPD这个工具进行需求、Bug管理。 操作流程 注册 TAPD&#xff0c;需要提供一个企业名新建一个项目&#…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

GitHub 趋势日报 (2025年06月06日)

&#x1f4ca; 由 TrendForge 系统生成 | &#x1f310; https://trendforge.devlive.org/ &#x1f310; 本日报中的项目描述已自动翻译为中文 &#x1f4c8; 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

6个月Python学习计划 Day 16 - 面向对象编程(OOP)基础

第三周 Day 3 &#x1f3af; 今日目标 理解类&#xff08;class&#xff09;和对象&#xff08;object&#xff09;的关系学会定义类的属性、方法和构造函数&#xff08;init&#xff09;掌握对象的创建与使用初识封装、继承和多态的基本概念&#xff08;预告&#xff09; &a…...