整个程序运作只会有此一个物件,不会创建第二个重复的物件
在实际情境中某些物件,比如连线 DB、与其他 service 长连线、取得环境 config,我们都希望可以整个运行环境「只有一个」,才不会造成资源的浪费,或者系统每个部分运行得到的值不同。
取得连线 DB 的物件,并且整个系统不会重复创建导致浪费 DB 连线的资源。
相关的 code 在Github - go-design-patterns
第一种方式(初始化即创建):在 import 模组的时候,将 db 透过init()
创建dbInstance{}
(init()
function 有着程序 runtime 会先行运行的特性),此後只有GetInstance()
这个公开方法可以取得dbInstance{}
,并无任何方法再创建dbInstance{}
优点:可以在初始化就创建 instance,不用等到呼叫才创建(第二种方式)
缺点:无法控制初始化的时间点,举例来说有可能「环境变数」套件都还没有初始化,db 就开始初始化了,导致读不到正确的环境变数
// db/db.go
package db
type DBInstance struct{}
var dbInstance *DBInstance
func init() {
dbInstance = &DBInstance{}
}
func GetInstance() *DBInstance {
return dbInstance
}
// main file
package main
import "DAY-18/db"
func main() {
db.GetInstance()
}
为了解决缺点,所以许多专案会不以init()
来初始化物件,而是任意一个公开方法来初始化:
// db-2/db-2.go file
package db
type DBInstance struct{}
var dbInstance *DBInstance
func InitDB() {
dbInstance = &DBInstance{}
}
func GetInstance() *DBInstance {
return dbInstance
}
// main file
package main
import db "DAY-18/db-2"
func main() {
db.Init()
db.GetInstance()
}
第二种方式(lazy 方式):在呼叫GetInstance()
的时候会做检查,如果dbInstance{}
不存在就创建,存在就回传现存的dbInstance{}
优点:可以在真的用到此物件时,才创建此物件,以节省记忆体,这即是 lazy 方式的优点
缺点:由於在使用物件时才会创建,所以第一次呼叫时需要创建会花较多的时间
package main
type DBInstance struct{}
var dbInstance *DBInstance
func GetInstance() *DBInstance {
if dbInstance == nil {
dbInstance = &DBInstance{}
}
return dbInstance
}
func main() {
GetInstance()
}
如果觉得if dbInstance == nil
的检查很麻烦的话,也可以用sync.Once{}
来实作,sync.Once{}.Do(func)
可以让 function 里的物件永远只执行一次,以达到 Singleton 的效果,里头适用 CAS 演算法来实作:
package main
import "sync"
type DBInstance struct{}
var (
dbInstance *DBInstance
once = &sync.Once{}
)
func GetInstance() *DBInstance {
once.Do(func() {
dbInstance = &DBInstance{}
})
return dbInstance
}
func main() {
GetInstance()
}
<<: [神经机器翻译理论与实作] 你只需要专注力(II): 建立更专注的seq2seq模型
>>: Day17 - 上架後台的商品列表页,今天只铺了 template
工程师太师了: 第9话 杂记: 最近在泡咖啡 被同事问说: 你一天都喝几杯咖啡阿? 我的回答:我大概...
如同学习函式一样!有时候我们会一直重复地做一件事, 当还是初学者的我们需要制作大量的个人资料物件时...
while 是循环结构(while一定要小写),while 後面搭配布林值(boolean)并用,F...
课程练习 串接 API 并可以呈现产品列表、加入购物车、购物车列表功能,表单送出前进行表单验证。 课...
在这次的专案开发有用到vector asset,里面有一些可以应用在专案开发的向量图形,如以下图形:...