文章目录
- [1. 概述](#1. 概述)
-
- [1.1 目的](#1.1 目的)
- [1.2 实现方式](#1.2 实现方式)
- [2. 代码示例](#2. 代码示例)
-
- [2.1 设计](#2.1 设计)
- [2.2 代码](#2.2 代码)
1. 概述
1.1 目的
- 保证类只有一个实例
- 有方法能让外部访问到该实例
1.2 实现方式
-
懒汉式
在第一次调用单例对象时创建该对象,这样可以避免不必要的资源浪费
-
饿汉式
在程序启动时就创建单例对象,这样可以提高程序的运行效率
-
双重检查锁
通过加锁来保证同一时刻只有一个线程可以创建单例对象
2. 代码示例
2.1 设计
以一个饿汉式模式为例
- 定义一个单例对象
king
- 它的
Get()
方法为外部提供访问
- 它的
- 声明一个变量
ourKing
,它的类型是单例对象king
- 定义一个函数
CreateKing()
用来实例化ourKing
- 定义初始化函数,调用函数
CreateKing()
实例化ourKing
- 调用
- 使用
ourKing
的Get()
方法访问单例对象 - 再次调用
CreateKing()
实例化ourKing
,并访问单例对象- 结果没有变化,说明第二次实例化没有执行
- 使用
如果使用懒汉式模式,在main()函数调用CreateKing()函数即可
2.2 代码
- han包
go
package main
import (
"fmt"
"sync"
)
// 定义单例对象
type king struct {
Name string
}
// 提供一个方法访问单例对象
func (k *king) Get() {
fmt.Printf("%s is king\n", k.Name)
}
var (
//保证后边创建函数只能执行一次
once sync.Once
//声明单一个变量类型是单例对象
ourKing *king
)
func init() {
//懒汉模式,启动时创建一个实例
CreateKing("汉献帝")
}
// 定义一个创建单例对象的函数
func CreateKing(name string) (k *king) {
once.Do(func() {
ourKing = &king{
Name: name,
}
})
return ourKing
}
func main() {
//查看该启动时实例化的单例
ourKing.Get()
//再次实例化,并且访问它,结果我们可以看见,没有创建新实例
CreateKing("曹贼").Get()
}
- 输出
shell
献帝 is king
献帝 is king
可见
SetKing
第二次并没有实现。