Go语言优雅实现单例模式的多种方式

 更新时间:2025年02月06日 08:20:36   作者:烛阴  
单例模式(Singleton Pattern)是一种设计模式,旨在保证一个类只有一个实例,并且提供全局访问点,单例模式通常用于需要限制某个对象的实例数量为一个的场景,本文给大家介绍了Go语言实现单例模式的多种方式,需要的朋友可以参考下

单例模式的基本定义

单例模式(Singleton Pattern)是一种设计模式,旨在保证一个类只有一个实例,并且提供全局访问点。单例模式通常用于需要限制某个对象的实例数量为一个的场景,比如数据库连接池、日志管理器、配置管理器等。

Go语言单例模式的实现

1. 线程安全的懒汉式单例

懒汉式的实现会延迟实例的创建,直到第一次调用时才会实例化对象。为了保证并发情况下的安全性,我们需要使用 sync.Once 来确保实例只会创建一次。

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup

// Singleton 类型
type Singleton struct {
}

var instance *Singleton
var once sync.Once

// GetInstance 提供全局唯一的实例
func GetInstance() *Singleton {

	once.Do(func() {
		instance = &Singleton{}
	})
	return instance
}

func main() {
	// 获取单例实例
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(index int) {
			defer wg.Done()
			s1 := GetInstance()
			fmt.Printf("index %d, memery address: %p\n", index, s1)
		}(i)

	}
	wg.Wait()
}

结果

index 0, memery address: 0x56c480
index 5, memery address: 0x56c480
index 4, memery address: 0x56c480
index 2, memery address: 0x56c480
index 7, memery address: 0x56c480
index 9, memery address: 0x56c480
index 6, memery address: 0x56c480
index 8, memery address: 0x56c480
index 3, memery address: 0x56c480
index 1, memery address: 0x56c480

解析:

  • sync.Once:Go标准库提供的一个同步原语,确保某个函数只会被调用一次。它在并发情况下保证了线程安全。
  • once.Do:此方法确保传入的函数只执行一次,适用于懒加载单例实例。

2. 双重检查锁定(DCL)

双重检查锁定是一种优化方式,它通过在两次检查实例时,减少了加锁的开销,提高了性能。

package main

import (
	"fmt"
	"sync"
)

var wg sync.WaitGroup

// Singleton 类型
type Singleton struct {
}

var instance *Singleton
var lock sync.Mutex

func GetInstance() *Singleton {
	if instance == nil {
		lock.Lock()
		defer lock.Unlock()
		if instance == nil {
			instance = &Singleton{}
		}
	}
	return instance
}

func main() {
	// 获取单例实例
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(index int) {
			defer wg.Done()
			s1 := GetInstance()
			fmt.Printf("index %d, memery address: %p\n", index, s1)
		}(i)

	}
	wg.Wait()
}

解析:

  • 双重检查:第一次检查实例是否为 nil,如果是,则加锁。然后再次检查实例是否为 nil,如果是则创建实例。
  • 锁的优化:只有在实例尚未创建时才会加锁,避免了每次获取实例时都需要加锁的性能损耗。

3. 原子操作法

Go 语言的 sync/atomic 包提供了原子操作,我们可以利用它来确保单例的线程安全。

package main

import (
	"fmt"
	"sync"
	"sync/atomic"
	"unsafe"
)

var wg sync.WaitGroup

type Singleton struct {
}

var instance unsafe.Pointer

func GetInstance() *Singleton {
	// 使用原子操作获取实例
	if atomic.LoadPointer(&instance) == nil {
		newInstance := &Singleton{}
		atomic.StorePointer(&instance, unsafe.Pointer(newInstance))
	}
	return (*Singleton)(atomic.LoadPointer(&instance))
}

func main() {
	// 获取单例实例
	for i := 0; i < 10; i++ {
		wg.Add(1)
		go func(index int) {
			defer wg.Done()
			s1 := GetInstance()
			fmt.Printf("index %d, memery address: %p\n", index, s1)
		}(i)

	}
	wg.Wait()
}

解析:

  • unsafe.Pointer:在Go中,unsafe.Pointer 可以用来绕过类型系统,直接处理内存地址。通过原子操作确保实例赋值的安全性。
  • atomic.LoadPointeratomic.StorePointer:原子加载和存储指针,确保操作的线程安全性。

总结

在Go语言中实现单例模式有多种方式,最常见的是使用 sync.Once、双重检查锁定(DCL)和原子操作法。每种方法有其优缺点,选择合适的方式可以帮助你在保证线程安全的前提下优化性能。

到此这篇关于Go语言优雅实现单例模式的多种方式的文章就介绍到这了,更多相关Go实现单例模式内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Golang通道阻塞情况与通道无阻塞实现小结

    Golang通道阻塞情况与通道无阻塞实现小结

    本文主要介绍了Golang通道阻塞情况与通道无阻塞实现小结,详细解析了通道的类型、操作方法以及垃圾回收机制,从基础概念到高级应用,具有一定的参考价值,感兴趣的可以了解一下
    2024-03-03
  • Go 实现HTTP中间人代理的操作

    Go 实现HTTP中间人代理的操作

    这篇文章主要介绍了Go 实现HTTP中间人代理的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • 详解Go 1.22 for循环的两处重要更新

    详解Go 1.22 for循环的两处重要更新

    这篇文章主要详细介绍了Go 1.22 for循环的两处重要更新,Go 1.22 版本于 2024 年 2 月 6 日发布,引入了几个重要的特性和改进,在语言层面上,这个版本对 for 循环进行了两处更新,本文将会对 for 循环的两个更新进行介绍,需要的朋友可以参考下
    2024-02-02
  • 关于golang中平行赋值浅析

    关于golang中平行赋值浅析

    这篇文章主要给大家介绍了关于golang中平行赋值的相关资料,文中通过示例代码介绍的非常详细,对大家学习或者使用golang具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-08-08
  • Go语言读取txt文档的操作方法

    Go语言读取txt文档的操作方法

    Go语言提供了很多文件操作的支持,在不同场景下,有对应的处理方式,本节我们来介绍一下Go语言读取txt文档的相关知识,感兴趣的朋友跟随小编一起看看吧
    2022-01-01
  • golang封装一个执行命令行的函数(return stderr/stdout/exitcode)示例代码

    golang封装一个执行命令行的函数(return stderr/stdout/exitcode)示例代码

    在 Go 语言中,您可以使用 os/exec 包来执行外部命令,不通过调用 shell,并且能够获得进程的退出码、标准输出和标准错误输出,下面给大家分享golang封装一个执行命令行的函数(return stderr/stdout/exitcode)的方法,感兴趣的朋友跟随小编一起看看吧
    2024-06-06
  • 教你一分钟配置好Go语言开发环境(多种操作系统)

    教你一分钟配置好Go语言开发环境(多种操作系统)

    在这篇文章中,我们从头到尾一步步指导你配置Golang开发环境,并编写你的第一个"Hello, World!"程序,我们详细解释了在多种操作系统(包括Windows、Linux和macOS)下的安装过程、环境变量设置以及如何验证安装是否成功
    2023-09-09
  • Go连接数据库操作基础讲解

    Go连接数据库操作基础讲解

    这篇文章主要为大家介绍了Go连接数据库操作基础讲解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-12-12
  • Go工具链之go tool cover使用方法和示例详解

    Go工具链之go tool cover使用方法和示例详解

    go tool cover是Go工具链中的一个命令,作用是分析测试用例的代码覆盖率,本文将对go tool cover 作用,使用方法和使用场景作一个简单的介绍,感兴趣的同学可以参考阅读一下
    2023-07-07
  • golang之数据验证validator的实现

    golang之数据验证validator的实现

    这篇文章主要介绍了golang之数据验证validator的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-10-10

最新评论