脚本之家,脚本语言编程技术及教程分享平台!
分类导航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服务器之家 - 脚本之家 - Golang - Golang基于sync.Once实现单例的操作代码

Golang基于sync.Once实现单例的操作代码

2022-10-31 10:24Hugo Lei Golang

这篇文章主要介绍了golang实现单例的操作代码,本文介绍基于sync.Once的方式来实现单例,熟练掌握这种模式,并理解其底层原理,对大部分人来讲已经完全够用了,需要的朋友可以参考下

在go里实现单例模式有多种方式:

  • 基于lock
  • 基于init函数
  • 基于sync.Once

本文介绍基于sync.Once的方式来实现单例,熟练掌握这种模式,并理解其底层原理,对大部分人来讲已经完全够用了。

基于sync.Once实现单例

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
// 其他package也可见,在其他地方也可以new新对象
// 但是最终调用Conn()方法时,都是用的single这个单例
// 1
type Driver struct {
    // 小写字母开头,外部不可访问,所以new个Driver新对象也没用
    // 2
    conn string
}
 
// 全局变量,指针默认值为nil
// 3
var single *Driver // 单例
var once sync.Once
 
// 对外暴露的公共方法
func (s *Driver) Conn() {
    fmt.Printf("conn=%s", single.conn) // do something
}
 
// 4
func GetDriverSingleton() *Driver {
    // 对GetDriverSingleton()方法的调用,都会执行once.Do()方法,只不过参数func()只会被执行一次
    // 若并发执行once.Do(),多个协程会阻塞,因内部是通过Mutex来控制
    once.Do(func() {
        single = new(Driver)
        single.conn = "single conn"
        time.Sleep(50 * time.Millisecond)
    })
    return single
}

单例类型定义Driver

Driver类的方法要支持跨包访问,因此需要以大写字母开头。
小写字母开头,作用域仅限于包内部。

类Field conn

类变量conn需要小写字母开头,跨包不可访问,避免在包外被修改。

但是包内还是有可能被修改。

once.Do(func() {})

每次调用GetDriverSingleton(),都会调用once.Do()方法,但是在once.Do()方法内部,仅会执行一次参数func(){},因此就保证了单例唯一初始化。

并发访问once.Do()

不会有并发访问问题,因once.Do()内部通过mutex来控制。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// once.DO()
if atomic.LoadUint32(&o.done) == 0 {
    // Outlined slow-path to allow inlining of the fast-path.
    o.doSlow(f)
}
 
// doSlow()
func (o *Once) doSlow(f func()) {
    o.m.Lock() // 互斥锁
    defer o.m.Unlock()
    if o.done == 0 {
        defer atomic.StoreUint32(&o.done, 1)
        f()
    }
}

对外暴露方法Conn()

外部对Conn()方法的调用,最终都由单例single来实现。

重新new(Driver)会发生什么?

很遗憾,无法将构造函数改成private,也就是说,在包外部是可以通过new(Driver)来创建新的对象。

但无论是哪个对象,对公开方法Conn()的调用,最终都是由单例single来执行的。

到此这篇关于golang实现单例的操作代码的文章就介绍到这了,更多相关go单例内容请搜索服务器之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持服务器之家!

原文链接:https://blog.csdn.net/hugo_lei/article/details/127537614

延伸 · 阅读

精彩推荐
  • Golanggolang解析html网页的方法

    golang解析html网页的方法

    今天小编就为大家分享一篇golang解析html网页的方法,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧 ...

    rambo_huang11962020-05-27
  • Golanggolang实现一个简单的websocket聊天室功能

    golang实现一个简单的websocket聊天室功能

    这篇文章主要介绍了golang实现一个简单的websocket聊天室功能,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要...

    CNBLOG9122021-11-18
  • GolangGo语言中一些不常见的命令参数详解

    Go语言中一些不常见的命令参数详解

    这篇文章主要给大家介绍了关于Go语言中一些不常见的命令参数的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学...

    John2662020-05-12
  • GolangGin 框架快速创建静态文件下载Web服务

    Gin 框架快速创建静态文件下载Web服务

    本文主要介绍了Gin 框架快速创建静态文件下载Web服务,文中通过示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下...

    尹东勋11502022-01-22
  • Golang解决Goland 提示 Unresolved reference 错误的问题

    解决Goland 提示 Unresolved reference 错误的问题

    这篇文章主要介绍了解决Goland 提示 Unresolved reference 错误的问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧...

    神神的蜗牛17262021-02-26
  • Golang读取Go项目中的配置文件的方法

    读取Go项目中的配置文件的方法

    本文主要介绍了读取Go项目中的配置文件的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面...

    范闲3672022-10-23
  • GolangGo实现各类限流的方法

    Go实现各类限流的方法

    这篇文章主要介绍了Go实现各类限流的方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着...

    JarvibDing10412021-06-26
  • GolangGoLang之标准库encoding/json包

    GoLang之标准库encoding/json包

    本文主要介绍了GoLang之标准库encoding/json包,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小...

    GoGo在努力7812022-08-17