Golang设计模式-单例模式

perfect6566 · · 822 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

单例模式

单例模式规定,一个类只能实例化一个实例。因此单例模的特点是:

  1. 只有一个实例
  2. 必须自行创建
  3. 必须自行向系统提供这个实例

应用场景

单例模式的主要使用场景有以下两个方面:

  1. 资源共享情况下避免资源操作导致的性能损耗,比如日志管理器,web网站计数器,应用配置管理对象等
  2. 方便对资源的控制,比如线程池和数据库连接池等

golang单例模式的实现方式

饿汉模式

直接创建好对象,这样不需要判断为空,同时也是线程安全。唯一的缺点是在导入包的同时会创建该对象,并持续占有在内存中。

var instance Tool

func GetInstance() *Tool {
    return &instance
}
懒汉模式

对象只有在调用GetInstance方法的时候才会实例化,节省资源。
golang 中懒汉模式可以有多种实现方式,本文用sync.once函数实现。

singleton.go :

package singleton

import "sync"

//定义包私有结构体
type singleton struct {
name string
}


var mysingleton *singleton
var once sync.Once

func Getinstance() *singleton {
//调用once.Do函数,进行实例化
    once.Do(func() {
        mysingleton=&singleton{}
    })

    return mysingleton
    
}

singleton_test.go :


package singleton

import (
    "log"
    "sync"
    "testing"
)

var w sync.WaitGroup

func TestSintonsample(t *testing.T)  {

    s1:=Getinstance()
    s2:=Getinstance()


    if s1==s2{
        log.Printf("s1 的地址是 %p,s2 的地址是 %p",s1,s2)
        log.Println("s1 和 s2 是相同的实例")
    }
}

func TestConcurrencesingleton (t *testing.T)  {

//设置100个goroutine,并发的实例化这个struct,对比每个实例是否相同
    singlelist:=make([]*singleton,0)
    for i:=0;i<100;i++{

        w.Add(1)
        go func(group sync.WaitGroup) {
            defer w.Done()
            singlelist=append(singlelist,Getinstance())

        }(w)
    }
    w.Wait()

    for i:=0;i<len(singlelist)-1;i++{

        if singlelist[i]!=singlelist[i+1]{
            t.Fatal("instance is not equal")
        }
    }

}

在目录下执行go test,可自动执行Test开头的测试函数,通过结果对比可以发现,单例模式实例化的对象的地址都是一样的。

2020/09/27 16:29:28 s1 的地址是 0xc00003e490,s2 的地址是 0xc00003e490
2020/09/27 16:29:28 s1 和 s2 是相同的实例
2020/09/27 16:29:28 s1 is 0xc00003e4b0,s2 is 0xc00003e4c0
PASS
ok      designpatten.com/singleton      3.342s

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

本文来自:简书

感谢作者:perfect6566

查看原文:Golang设计模式-单例模式

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

822 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传