Go單例模式

單例模式回顧

之前在作java的時候,常常會用到設計模式,如單例模式、工廠模式、觀察者模式等。其實設計模式和語言無關,先簡單回顧下單例模式吧,單例模式是一種用在特定場景的設計模式。好比,讀取程序的配置文件的時候就會用到單例模式。java

想象一下,假若有個類的實例是來對配置文件進行操做,若是不用單例模式,系統中任何用到讀取配置文件的地方都將會建立一個對象,這得多麼浪費內存。golang

實際上改對象只須要被實例化一次便可。單例模式的抽象表達就是:在程序中咱們只須要某個類實例化一次便可,保證一個類僅有一個實例,並提供一個獲取實例的方法。設計模式

單例模式的實現

單例模式有懶漢式和餓漢式。在用Go實現以前,先看看Java的實現。
在java中無論是懶漢式仍是餓漢式都會將構造方法私有化。這點不用解釋,由於不須要經過外部來實例化對象,把建立對象的權限封鎖。安全

懶漢式

所謂懶漢式,也就是在建立對象時比較懶嘛,先不着急建立對象,在須要的時候才建立對象。這裏看下java的實現,暫不考慮併發問題,併發加上synchronized便可。併發

1 public class Singleton {
 2    private static Singleton single = null;
 3    private Singleton(){
 4    }
 5    public static Singleton getSingle() {
 6        if (single == null) {
 7            single = new Singleton();
 8        }
 9        return single;
10    }
11}

那麼上面的設計模式可否用Go語言實現呢?答案是確定的。Go語言沒有private這樣的權限控制,很簡單的是經過首字母大小寫來控制外部是否可以訪問。函數

1 type config struct {
 2 }
 3
 4 var cfg *config
 5 func getInstane() *config {
 6     if cfg == nil { 
 7             cfg = new(Config)
 8             return cfg 
 9     }
10    return cfg
11}

上面沒有考慮線程安全,咱們能夠本身加鎖保證安全,也能夠用Golang 中的sync.Once結構體,該結構體提供了一個Do方法,Do函數裏面的函數只有在第一次纔會被調用,該方法只會生成一個實例,且也是線程安全的。線程

1 type config struct {
 2 }
 3
 4 var cfg *config
 5 var oSingle sync.Once
 6
 7 func getInstane() *config {
 8    oSingle.Do(
 9        func() {
10            cfg = new(config)
11        })
12    return cfg
13 }

餓漢式

餓漢模式和懶漢模式不一樣的只是在提供獲取實例的方法上。仍是先來看下java的餓漢模式:設計

1 public class Singleton {
2    private static Singleton single = new Singleton();// 只會建立一次實例
3    private Singleton(){
4    }
5    public static Singleton getSingle() {
6        return single; // 直接返回
7 }

在go語言中,餓漢模式能夠直接在init函數中初始化或者直接在全局變量中聲明。這區別於java中的變量必須是由static修飾。由於static變量在類加載的時候進行初始化。多個實例會共享這塊內存空間。code

關於爲何能夠直接用全局變量,下回再討論golang中的全局變量。對象

1 type cfg struct {    
 2 } 
 3 var cfg *config
 4 func init()  {
 5    cfg = new(config)
 6 }
 7 // NewConfig 提供獲取實例的方法...
 8 func NewConfig() *config {
 9    return cfg
10 }
1 type config struct {    
2 } 
3 var cfg *config = new(config)
4 // NewConfig 提供獲取實例的方法...
5 func NewConfig() *config {
6    return cfg
7 }
相關文章
相關標籤/搜索