跳过正文
  1. 文章/
  2. GoLang/
  3. 设计模式/

1、单例模式

·503 字·2 分钟· loading · loading · ·
GoLang 设计模式
GradyYoung
作者
GradyYoung
设计模式 - 点击查看当前系列文章
§ 1、单例模式 「 当前文章 」

单例模式(Singleton)确保一个类只有一个实例,并提供对该实例的全局访问点。

Go语言实现单例模式的有四种方式,分别是懒汉式、饿汉式、双重检查和 sync.Once。

懒汉式
#

非线程安全
#

package main

type Apple struct {
}

//私有变量
var apple *Apple

// GetAppleInstants 获取Apple实例
func GetAppleInstants() *Apple {
	if apple == nil {
		apple = new(Apple)
	}
	return apple
}

线程安全
#

双重检查锁
#

package main

import "sync"

//锁对象
var lock sync.Mutex

type Apple struct {
}

//私有变量
var apple *Apple

// GetAppleInstants 获取Apple实例
func GetAppleInstants() *Apple {
	if apple == nil {
		lock.Lock()
		defer lock.Unlock()
		if apple == nil {
			apple = new(Apple)
		}
	}
}

sync.Once
#

通过 sync.Once 来确保创建对象的方法只执行一次

package main

import "sync"

type Apple struct {
}
//once对象
var once sync.Once

//私有变量
var apple *Apple

// GetAppleInstants 获取Apple实例
func GetAppleInstants() *Apple {
	once.Do(func() {
		apple = new(Apple)
	})
}

sync.Once 内部本质上也是双重检查的方式,但在写法上会比自己写双重检查更简洁,以下是 Once 的源码

func (o *Once) Do(f func()) {
  //判断是否执行过该方法,如果执行过则不执行
    if atomic.LoadUint32(&o.done) == 1 {
        return
    }
    // Slow-path.
    o.m.Lock()
    defer o.m.Unlock()
  //进行加锁,再做一次判断,如果没有执行,则进行标志已经扫行并调用该方法
    if o.done == 0 {
        defer atomic.StoreUint32(&o.done, 1)
        f()
    }
}

饿汉式
#

使用全局变量
#

package main

type Apple struct {
}
//私有变量
var apple = new(Apple)

// GetAppleInstants 获取Apple实例
func GetAppleInstants() *Apple {
	return apple
}

使用init函数
#

package main

type Apple struct {
	
}
//私有变量
var apple *Apple

func init()  {
	apple = new(Apple)
}

// GetAppleInstants 获取Apple实例
func GetAppleInstants() *Apple {
	return apple
}
设计模式 - 点击查看当前系列文章
§ 1、单例模式 「 当前文章 」