Go 语言单例模式示例详解

 更新时间:2022年10月31日 09:10:03   作者:六号积极分子  
这篇文章主要为大家介绍了Go 语言单例模式示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

简单单例模式

单例模式是创建类型的模式,它是为了保证执行期间内只有一个实例。使用 Golang 指针可以很容易的实现单例模式,通过指针保持相同的引用。

package singleton
type singleton struct{}
var instance = &singleton{}
func getSingleton() *singleton {
    return instance
}

可以看到整个单例模式 由以下部分组成:

  • 私有结构类型,在本例中为 singleton。
  • 指向 singletonCon 类型的私有变量 instance。
  • 一个获取singleton 结构体的函数 getSingleton。

但 getSingleton 函数是直接就返回实例,即包加载时立即被创建。如果单例实例化时初始内容过多,就会导致程序加载用时较长。

进一步优化的方式就是要先用于验证 singletonCon 是否已经初始化。

func getSingleton() *singleton {
    if instance ==nil {
     return instance  = &singleton{}
   }
    return instance
}

通过判断实例是否nil 也不是很可靠。因为如果是多个协程 goroutine 同时调用该函数时,就无法保证并发安全。

加锁的单例模式

解决并发安全最简单的方法就是加锁,可以使用 sync.Mutex 解决。

var mutex sync.Mutex
func getSingleton() *singleton {
    mutex.Lock()
    defer mutex.Unlock()
    if instance ==nil {
     return instance  = &singleton{}
   }
    return instance
}

每次获取对象都需要获取锁然后再判断是否 nil。如果在高度的并发环境下,可能就会导致性能问题。因为其每个协程都需要加锁解锁,就会导致程序性能下降。

双check 的单例模式

加锁有性能问题,不加锁会有并发问题。所以有人提出另一种解决方法:双重锁定的方案。

func getSingleton() *singleton {
  if instance ==nil {
    mutex.Lock()
    defer mutex.Unlock()
    if instance ==nil {
     return instance  = &singleton{}
     }
   }
    return instance
}

使用两层的 instance == nil 的判断,再在中间加锁。第一层判断可以提告程序效率,不用每次都加锁,非 nil 就可以直接返回实例。第二层的判断就是为了解决并发安全的问题,解决多个协程 goroutine 同时都要加锁时,再由这二层做区分。

sync.Once 的单例模式

可能其他语言会用上面的解决方式,但是在 GO 中有一个 sync.Once 的机制可以优化以上的代码:

var once sync.Once
func getSingleton() *singleton {
    once.Do(func() {
        instance = &singleton{}
    })
    return instance
}

sync.Once 是 Go 标准库提供的使函数只执行一次的实现。所以它可以保证多个协程 goroutine 同时执行时但是实例只会被创建一次。

Sync.Once 常用的场景:初始化配置,保持数据库连接。所以当一个变量有且仅当第一次被访问时进行初始化,且只初始化一次,就可以使用 sync.Once 控制其初始化。

以上就是Go 语言单例模式示例详解的详细内容,更多关于Go 语言单例模式的资料请关注脚本之家其它相关文章!

相关文章

  • Go模板template用法详解

    Go模板template用法详解

    这篇文章主要介绍了Go标准库template模板用法详解;包括GO模板注释,作用域,语法,函数等知识,需要的朋友可以参考下
    2022-04-04
  • sublime text3解决Gosublime无法自动补全代码的问题

    sublime text3解决Gosublime无法自动补全代码的问题

    本文主要介绍了sublime text3解决Gosublime无法自动补全代码的问题,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-01-01
  • Go疑难杂症讲解之为什么nil不等于nil

    Go疑难杂症讲解之为什么nil不等于nil

    在日常开发中,可能一不小心就会掉进 Go 语言的某些陷阱里,而本文要介绍的 nil ≠ nil 问题,感兴趣的小伙伴可以跟随小编一起了解一下
    2022-10-10
  • 对Golang import 导入包语法详解

    对Golang import 导入包语法详解

    今天小编就为大家分享一篇对Golang import 导入包语法详解,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2019-06-06
  • intelliJ idea安装go开发环境并搭建go项目(打包)全过程

    intelliJ idea安装go开发环境并搭建go项目(打包)全过程

    最近在配置idea开发go语言时碰到很多问题,所以这里给大家总结下,这篇文章主要给大家介绍了关于intelliJ idea安装go开发环境并搭建go项目(打包)的相关资料,需要的朋友可以参考下
    2023-10-10
  • golang http使用踩过的坑与应对方式

    golang http使用踩过的坑与应对方式

    这篇文章主要介绍了golang http使用踩过的坑与应对方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2024-01-01
  • Go语言基础函数包的使用学习

    Go语言基础函数包的使用学习

    本文通过一个实现加减乘除运算的小程序来介绍go函数的使用,以及使用函数的注意事项,并引出了对包的了解和使用,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-05-05
  • golang 占位符和fmt常见输出介绍

    golang 占位符和fmt常见输出介绍

    这篇文章主要介绍了golang 占位符和fmt常见输出介绍,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2020-12-12
  • Go语言中匿名嵌套和类型嵌套的区别解析

    Go语言中匿名嵌套和类型嵌套的区别解析

    在Go语言中,匿名嵌套结构体和与类型同名的嵌套结构体不是完全等价的,它们有一些重要的区别,这篇文章主要介绍了Go语言中匿名嵌套和类型嵌套的区别,需要的朋友可以参考下
    2023-09-09
  • golang中json操作的完全指南

    golang中json操作的完全指南

    golang标准库有一个名叫encoding/json的包,包含了JSON的序列化(Marshal)和反序列化(Unmarshal)的能力,下面这篇文章主要给大家介绍了关于golang中json操作的相关资料,需要的朋友可以参考下
    2022-07-07

最新评论