Go設計模式:單例模式

package main

import (
	"fmt"
	"sync"
	"time"
)

func main() {
	// 演示懶漢式
	go func() {
		s := NewLazySingleton()
		s.Say()
	}()
	singleton := NewLazySingleton()
	singleton.Say()

	// 演示餓漢式
	go func() {
		h := NewHungrySingleton()
		h.Say()
	}()
	hungry := NewHungrySingleton()
	hungry.Say()

	time.Sleep(time.Second)
}

// 定義一個結構體(至關於面嚮對象語言裏面的class)
type Singleton struct {
	name string
}

// 至關於class的方法
func (s Singleton) Say() {
	fmt.Printf("%s: Say Hello\n", s.name)
}

// 因爲Go並非徹底面向對象的語言,只能經過包級別的全局變量模擬類變量
var lazyInstance *Singleton

// 爲了Go協程併發安全,能夠加鎖,若是不加鎖第一次實例化的時候會出現data race操做,可是其實並不影響功能
// 第一加鎖方式是使用mutex
// mu.lock
// defer mu.unlock
// 可是這樣並不優雅,至關於每次New的時候都得加鎖,影響性能,因此最好的方式是使用once
var once sync.Once

// 懶漢式,所謂懶漢式就是比較懶,等你第一次調用的時候纔會去實例化對象
func NewLazySingleton() *Singleton {
	once.Do(func() {
		fmt.Println("init lazy")
		lazyInstance = &Singleton{name: "lazy"}
	})
	return lazyInstance
}

var hungryInstance = Singleton{name: "hungry"}

// 餓漢式,所謂餓漢式就是在你調用New以前就已經初始化好了,這個更簡單,並且也不須要鎖
func NewHungrySingleton() *Singleton {
	return &hungryInstance
}
複製代碼

單例模式在實際開發中用的仍是比較的多,好比數據庫鏈接池、配置文件等數據庫

相關文章
相關標籤/搜索