什么是单例设计模式
结构中只包含一个被称为单例的特殊类,能够保证系统运行中一个类只创建一个实例
实现方式:
懒汉式
饿汉式
双重检查
sync.Once
懒汉式
特点:
非线程安全,多线程下可能会创建多次对象:
package Practice_Single
/*
设置结构体
建立私有变量用来返回结构体
提供获取该结构体实例的函数
*/
/* 设置结构体 */
type Tool struct {
// 定义属性
values int
}
/* 设置私有变量用于获取该结构体实例 */
/*
这样做方便切换实例化的结构体
*/
var instance *Tool
/* 定义构建私有变量实例的函数 */
func GetInstance() *Tool {
if instance == nil {
instance = new(Tool)
}
return instance
}
在非线程安全下进行加锁保证线程安全:
/* 进行加锁操作 */
var lock sync.Mutex
/* 定义构建私有变量实例的函数 */
func GetInstance() *Tool {
// 先上锁
lock.Lock()
// 异常处理
defer lock.Unlock()
if instance == nil {
instance = new(Tool)
}
return instance
}
饿汉式
特点:
直接创建好对象,不需要判断为空,同时也是线程安全
缺点: 在导入包的同时会创建该对象,并持续占有在内存中
饿汉式可以使用init
函数也可以使用全局变量:
init
函数:
package Practice_Single
/*
新建结构体
新建单例常量
使用init函数初始化
使用全局变量初始化
*/
type config struct {
}
// 设置单例变量
var cfg *config
// 通过init函数进行初始化
func init() {
cfg = new(config)
}
// 提供获取实例的函数
func NewConfig() *config {
return cfg
}
全局变量:
// 提供全局变量获取--->所谓全局变量就是将实例声明为一个包内可使用的变量通过方法获取该变量
var cfg1 = new(config)
// 提供获取变量cfg1的函数
func NewConfigGal() *config {
return cfg1
}
双重检查
特点:
在懒汉式的基础上进行优化,减少加锁的操作,既保证线程安全又不影响性能
package Practice_Single
import "sync"
var lockFirst sync.Mutex
/*
第一次判断不加锁
第二次加锁保证线程安全
一旦对象建立,获取对象就不用加锁了
*/
func GetInstanceFirst() *Tool {
if instance == nil {
// 第一次创建对象,进行加锁操作
lockFirst.Lock()
// 第一次创建对象
if instance == nil {
instance = new(Tool)
}
// 第一次创建对象后就施放对象
lockFirst.Unlock()
}
// 返回线程对象--->如果对象不为空直接返回
return instance
}
sync.Once
使用sync
包下的函数创建对象
package Practice_Single
import "sync"
/*
使用sync包下的类型进行对象创建
*/
var once sync.Once
// 通过once变量执行接口当中的do方法创建对象
func GetInstanceOnce() *Tool {
once.Do(func() {
instance = new(Tool)
})
// 返回对象
return instance
}