Golang单例模式

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

懒汉模式(Lazy Loading)

懒汉模式是开源项目中使用最多的一种,最大的缺点是非线程安全的

type singleton struct {
}

// private
var instance *singleton

// public
func GetInstance() *singleton {
    if instance == nil {
        instance = &singleton{}     // not thread safe
    }
    return instance
}

带锁的单例模式

type singleton struct {
}

var instance *singleton
var mu sync.Mutex

func GetInstance() *singleton {
    mu.Lock()
    defer mu.Unlock()

    if instance == nil {
        instance = &singleton{}     // unnecessary locking if instance already created
    }
    return instance
}

这里使用了Go的sync.Mutex,其工作模型类似于Linux内核的futex对象,具体实现极其简单,性能也有保证初始化时填入的0值将mutex设定在未锁定状态,同时保证时间开销最小这一特性允许将mutex作为其它对象的子对象使用

带检查锁的单例模式

    if instance == nil {     // <-- Not yet perfect. since it's not fully atomic
        mu.Lock()
        defer mu.Unlock()
 
        if instance == nil {
            instance = &singleton{}
        }
    }
    return instance
}

这是一个不错的方法,但是还并不是很完美。因为编译器优化没有检查实例存储状态。如果使用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
}

比较好的一种方式sync.Once

import (
    "sync"
)
 
type singleton struct {
}
 
var instance *singleton
var once sync.Once
 
func GetInstance() *singleton {
    once.Do(func() {
        instance = &singleton{}
    })
    return instance
}

引文:

https://xiequan.info/go%E7%9A%84%E5%8D%95%E4%BE%8B%E6%A8%A1%E5%BC%8F/

本文分享自微信公众号 - Golang语言社区(Golangweb)

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-11-13

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏非典型技术宅

Swift多线程:使用Thread进行多线程间通讯,协调子线程任务1. Thread的三种建立方式2. Thread的基本使用3. 使用NSCondition实现线程间通讯4. pthread

24920
来自专栏mini188

聊聊从web session的共享到可扩展缓存设计

先从web session的共享说起 许多系统需要提供7*24小时服务,这类系统肯定需要考虑灾备问题,单台服务器如果宕机可能无法立马恢复使用,这必定影响到服务。...

22860
来自专栏程序猿DD

程序员你为什么这么累【续】:编码习惯之参数校验和国际化规范

今天我们说说参数校验和国际化,这些代码没有什么技术含量,却大量充斥在业务代码上,很可能业务代码只有几行,参数校验代码却有十几行,非常影响代码阅读,所以很有必要把...

22870
来自专栏JavaEdge

LDAP认证模式简介1. 目录服务2. LDAP特点3. LDAP组织数据的方式4. 基本概念

目录是一个为查询、浏览和搜索而优化的专业分布式数据库,它呈树状结构组织数据,就好像Linux/Unix系统中的文件目录一样 目录数据库和关系数据库不同,它有优...

33130
来自专栏Python爬虫实战

Python爬虫之二:自制简易词典

运行平台: Windows Python版本: Python3.6 IDE: PyCharm 其他工具: Chrome浏览器

14720
来自专栏更流畅、简洁的软件开发方式

Step By Step 一步一步写网站[1] —— 填加数据

填加数据是一个项目必不可少的部分,也是一个基础操作,使用也是最频繁的。 那么您是怎么实现添加数据的呢? 添加数据可以分为几种情况。 1、单表添加,不需要事务。...

224100
来自专栏杨建荣的学习笔记

同样的sql执行结果不同的原因分析 (r4笔记第27天)

今天开发的同事问我一个问题,说有一个sql语句,在weblogic的日志中执行没有结果,但是手动拷贝数据到客户端执行,却能够查到。这种奇怪的问题一下子就能引起我...

30780
来自专栏Java3y

Activiti就是这么简单

Activiti介绍 什么是Activiti? Activiti5是由Alfresco软件在2010年5月17日发布的业务流程管理(BPM)框架,它是覆盖了业务...

87580
来自专栏IT大咖说

基于PG数据库插件的SQL规范审核工具

内容来源:2017 年 10 月 21 日,平安科技数据库架构师陈刚在“PostgreSQL 2017中国技术大会”进行《基于PG数据库插件的SQL规范审核工具...

25520
来自专栏知识分享

51单片机开发板(W25Q16学习)

---恢复内容开始--- 今天测试开发板的W25Q16(16Mbit--Flash)写一篇文章备忘一下 先说一下容量的单位 计算机存储单位一般用B,KB、MB、...

36240

扫码关注云+社区

领取腾讯云代金券