golang mysql 单例_Go的单例模式 - Go语言中文社区

golang mysql 单例_Go的单例模式


单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。

1.Go实现非线程安全的单例模式(懒汉 就是很懒的单例 哈哈):

package singleton

type singleton struct {

}

var instance *singleton

func GetInstance() *singleton {

if instance == nil {

instance = &singleton{} //

}

return instance

}

1

2

3

4

5

6

7

8

9

10

11

12

13

packagesingleton

typesingletonstruct{

}

varinstance *singleton

funcGetInstance()*singleton{

ifinstance==nil{

instance=&singleton{}//

}

returninstance

}

非线程安全的单例模式是大家用得最多的一种。在Github上面的开源项目有很多都使用了非线程安全的。

这种写法lazy loading很明显,但是致命的是在多线程不能正常工作。

2.Go实现带线程锁的单例模式

var mu Sync.Mutex

func GetInstance() *singleton {

mu.Lock() //

defer mu.Unlock()

if instance == nil {

instance = &singleton{}

}

return instance

}

1

2

3

4

5

6

7

8

9

10

11

varmuSync.Mutex

funcGetInstance()*singleton{

mu.Lock()//

defermu.Unlock()

ifinstance==nil{

instance=&singleton{}

}

returninstance

}

这里用了Go的

Sync.Mutex

1

Sync.Mutex

sync/mutex是Go语言底层基础对象之一,用于构建多个goroutine间的同步逻辑,因此被大量高层对象所使用。

其工作模型类似于Linux内核的futex对象,具体实现极为简洁,性能也有保证。

mutex对象仅有两个数值字段,分为为state(存储状态)和sema(用于计算休眠goroutine数量的信号量)。

初始化时填入的0值将mutex设定在未锁定状态,同时保证时间开销最小。

这一特性允许将mutex作为其它对象的子对象使用。

3.带检查锁的的单例模式

func GetInstance() *singleton {

if instance == nil { //

mu.Lock()

defer mu.Unlock()

if instance == nil {

instance = &singleton{}

}

}

return instance

}

1

2

3

4

5

6

7

8

9

10

11

funcGetInstance()*singleton{

ifinstance==nil{//

mu.Lock()

defermu.Unlock()

ifinstance==nil{

instance=&singleton{}

}

}

returninstance

}

这是一个不错的方法,但是还并不是很完美。因为编译器优化没有检查实例存储状态。如果使用sync/atomic包的话 就可以自动帮我们加载和设置标记。

import "sync"

import "sync/atomic"

var initialized uint32

...

func GetInstance() *singleton {

if atomic.LoadUInt32(&initialized) == 1 {

return instance

}

mu.Lock()

defer mu.Unlock()

if initialized == 0 {

instance = &singleton{}

atomic.StoreUint32(&initialized, 1)

}

return instance

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

import"sync"

import"sync/atomic"

varinitializeduint32

...

funcGetInstance()*singleton{

ifatomic.LoadUInt32(&initialized)==1{

returninstance

}

mu.Lock()

defermu.Unlock()

ifinitialized==0{

instance=&singleton{}

atomic.StoreUint32(&initialized,1)

}

returninstance

}

个人觉得比较好的在go中使用单例设计的是这种

package singleton

import (

"sync"

)

type singleton struct {

}

var instance *singleton

var once sync.Once

func GetInstance() *singleton {

once.Do(func() {

instance = &singleton{}

})

return instance

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

packagesingleton

import(

"sync"

)

typesingletonstruct{

}

varinstance *singleton

varoncesync.Once

funcGetInstance()*singleton{

once.Do(func(){

instance=&singleton{}

})

returninstance

}

通过使用sync.Once 包可以实现线程安全的单例模式。

如果写得有什么不对地方欢迎指出。

Go的单例模式

有疑问加站长微信联系(非本文作者)

5c5fbae790ec0313d6ee17e8b3dd9ba1.png

版权声明:本文来源CSDN,感谢博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
原文链接:https://blog.csdn.net/weixin_36194075/article/details/113385381
站方申明:本站部分内容来自社区用户分享,若涉及侵权,请联系站方删除。
  • 发表于 2021-06-14 20:04:37
  • 阅读 ( 847 )
  • 分类:数据库

0 条评论

请先 登录 后评论

官方社群

GO教程

猜你喜欢