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

 更新时间:2025年07月29日 10:55:33   作者:喜欢代码的新之助  
单例模式是一种创建型设计模式,Go中常见实现包括使用sync.Once、双重检查锁定和原子操作法,每种方法都有其独特的优点和适用场景,下面就来具体介绍一下

单例模式的基本定义

单例模式(Singleton Pattern)是一种创建型设计模式,其核心思想在于确保一个类仅有一个实例,并提供一个全局访问点。该模式广泛应用于需要严格控制对象数量的场景,诸如数据库连接池、日志管理器、配置管理器等。

Go语言中的单例模式实现

在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, memory address: %p\n", index, s1)
		}(i)
	}
	wg.Wait()
}

解析

  • sync.Once:确保传入的函数只执行一次,适用于懒加载单例实例。
  • 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, memory address: %p\n", index, s1)
		}(i)
	}
	wg.Wait()
}

解析

  • 双重检查:第一次无锁检查避免不必要的加锁开销,第二次加锁检查确保实例安全创建。
  • 锁优化:仅在实例尚未创建时加锁,提高了性能。

3. 原子操作法

利用sync/atomic包提供的原子操作,确保单例的线程安全。

package main
 
import (
	"fmt"
	"sync"
	"sync/atomic"
	"unsafe"
)
 
var wg sync.WaitGroup
 
// Singleton 结构体定义
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, memory address: %p\n", index, s1)
		}(i)
	}
	wg.Wait()
}

解析

  • unsafe.Pointer:用于直接处理内存地址,绕过类型系统。
  • atomic.LoadPointeratomic.StorePointer:原子加载和存储指针,确保线程安全。

总结

在Go语言中,实现单例模式有多种方法,包括使用sync.Once、双重检查锁定和原子操作法。每种方法都有其独特的优点和适用场景。选择哪种方法取决于具体需求,如性能要求、代码简洁性等。在实际应用中,可以根据具体场景权衡利弊,选择最合适的实现方式。

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

相关文章

  • Golang实现简单http服务器的示例详解

    Golang实现简单http服务器的示例详解

    这篇文章主要为大家详细介绍了如何利用Golang实现简单http服务器,文中的示例代码讲解详细,对我们学习Golang有一定的帮助,需要的可以参考一下
    2023-03-03
  • Windows下安装VScode 并使用及中文配置方法

    Windows下安装VScode 并使用及中文配置方法

    这篇文章主要介绍了Windows下安装VScode 并使用及中文配置的方法详解,本文通过图文并茂的形式给大家介绍,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2020-03-03
  • 深入浅出Go语言:手把手教你高效生成与解析JSON数据

    深入浅出Go语言:手把手教你高效生成与解析JSON数据

    本文将带你一步步走进Go语言的世界,教你如何高效生成与解析JSON数据,无论你是初学者还是经验丰富的开发者,都能在本文中找到实用的技巧和灵感,本文内容简洁明了,示例丰富,让你在阅读的过程中轻松掌握Go语言生成与解析JSON数据的技巧,需要的朋友可以参考下
    2024-02-02
  • golang判断结构体为空的问题

    golang判断结构体为空的问题

    这篇文章主要介绍了golang判断结构体为空的问题,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-02-02
  • Golang对sqlite3数据库进行操作实践记录

    Golang对sqlite3数据库进行操作实践记录

    sqlite是嵌入式关系型数据库引擎,官方描述为自包含的、无服务的、零配置并支持事务的关系型数据库引擎,下面这篇文章主要给大家介绍了关于Golang对sqlite3数据库进行操作的相关资料,需要的朋友可以参考下
    2024-03-03
  • Golang Makefile示例深入讲解使用

    Golang Makefile示例深入讲解使用

    一次偶然的机会,在 github 上看到有人用 Makefile,就尝试了一下,发现真的非常合适,Makefile 本身就是用来描述依赖的,可读性非常好,而且与强大的 shell 结合在一起,基本可以实现任何想要的功能
    2023-01-01
  • 超实用的Golang通道指南之轻松实现并发编程

    超实用的Golang通道指南之轻松实现并发编程

    Golang 中的通道是一种高效、安全、灵活的并发机制,用于在并发环境下实现数据的同步和传递。本文主要介绍了如何利用通道轻松实现并发编程,需要的可以参考一下
    2023-04-04
  • Golang实现IO操作

    Golang实现IO操作

    本文主要介绍了Golang实现IO操作,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2024-05-05
  • 快速上手GO的net/http包

    快速上手GO的net/http包

    本文主要介绍了快速上手GO的net/http包,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2025-05-05
  • golang使用grpc+go-kit模拟oauth认证的操作

    golang使用grpc+go-kit模拟oauth认证的操作

    这篇文章主要介绍了golang使用grpc+go-kit模拟oauth认证的操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04

最新评论