欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

詳解Go語言設計模式之單例模式

 更新時間:2022年10月21日 11:36:15   作者:宇宙之一粟  
單例模式很容易記住。就像名稱一樣,它只能提供對象的單一實例,保證一個類只有一個實例,并提供一個全局訪問該實例的方法。本文就來聊聊Go語言中的單例模式,感興趣的小伙伴可以了解一下

單例模式的概念

單例模式很容易記住。就像名稱一樣,它只能提供對象的單一實例,保證一個類只有一個實例,并提供一個全局訪問該實例的方法。

在第一次調用該實例時被創(chuàng)建,然后在應用程序中需要使用該特定行為的所有部分之間重復使用。

單例模式結構

單例模式的使用場景

你會在許多不同的情況下使用單例模式。比如:

  • 當你想使用同一個數(shù)據庫連接來進行每次查詢時
  • 當你打開一個安全 Shell(SSH)連接到一個服務器來做一些任務時。 而不想為每個任務重新打開連接
  • 如果你需要限制對某些變量或空間的訪問,你可以使用一個單例作為 作為這個變量的門(在 Go 中使用通道可以很好地實現(xiàn))
  • 如果你需要限制對某些空間的調用數(shù)量,你可以創(chuàng)建一個單例實例使得這種調用只在可接受的窗口中進行

單例模式還有跟多的用途,這里只是簡單的舉出一些。

單例模式例子:特殊的計數(shù)器

我們可以寫一個計數(shù)器,它的功能是用于保存它在程序執(zhí)行期間被調用的次數(shù)。這個計數(shù)器的需要滿足的幾個要求:

  • 當之前沒有創(chuàng)建過計數(shù)器 count 時,將創(chuàng)建一個新的計數(shù)器 count = 0
  • 如果已經創(chuàng)建了一個計數(shù)器,則返回此實例實際保存的 count 數(shù)
  • 如果我們調用方法 AddOne 一次,計數(shù) count 必須增加 1

在這個場景下,我們需要有 3 個測試來堅持我們的單元測試。

第一個單元測試

與 Java 或 C++ 這種面向對象語言中不同,Go 實現(xiàn)單例模式沒有像靜態(tài)成員的東西(通過 static 修飾),但是可以通過包的范圍來提供一個類似的功能。

首先,我們要為單例對象編寫包的聲明:

package singleton

type Singleton struct {
	count int
}

var instance *Singleton

func init() {
	instance = &Singleton{}
}

func GetInstance() *Singleton {
	return nil
}

func (s *Singleton) AddOne() int {
	return 0
}

然后,我們通過編寫測試代碼來驗證我們聲明的函數(shù):

package singleton

import (
	"testing"
)

func TestGetInstance(t *testing.T) {
	count := GetInstance()

	if count == nil {

		t.Error("A new connection object must have been made")
	}

	expectedCounter := count

	currentCount := count.AddOne()
	if currentCount != 1 {
		t.Errorf("After calling for the first time to count, the count must be 1 but it is %d\n", currentCount)

	}

	count2 := GetInstance()
	if count2 != expectedCounter {
		t.Error("Singleton instances must be different")
	}

	currentCount = count2.AddOne()

	if currentCount != 2 {
		t.Errorf("After calling 'AddOne' using the second counter, the current count must be 2 but was %d\n", currentCount)
	}
}

第一個測試是檢查是顯而易見,但在復雜的應用中,其重要性也不小。當我們要求獲得一個計數(shù)器的實例時,我們實際上需要得到一個結果。

我們把對象的創(chuàng)建委托給一個未知的包,而這個對象在創(chuàng)建或檢索對象時可能失敗。我們還將當前的計數(shù)器存儲在變量 expectedCounter 中,以便以后進行比較。即:

	currentCount := count.AddOne()
	if currentCount != 1 {
		t.Errorf("After calling for the first time to count, the count must be 1 but it is %d\n", currentCount)

	}

運行上面的代碼:

$ go test -v -run=GetInstance .
=== RUN   TestGetInstance
    singleton_test.go:12: A new connection object must have been made
    singleton_test.go:19: After calling for the first time to count, the count must be 1 but it is 0
    singleton_test.go:31: After calling 'AddOne' using the second counter, the current count must be 2 but was 0
--- FAIL: TestGetInstance (0.00s)
FAIL
FAIL    github.com/yuzhoustayhungry/GoDesignPattern/singleton   0.412s
FAIL

單例模式實現(xiàn)

最后,我們必須實現(xiàn)單例模式。正如我們前面提到的,通常做法是寫一個靜態(tài)方法和實例來檢索單例模式實例。

在 Go 中,沒有 static 這個關鍵字,但是我們可以通過使用包的范圍來達到同樣的效果。

首先,我們創(chuàng)建一個結構體,其中包含我們想要保證的對象 在程序執(zhí)行過程中成為單例的對象。

package singleton

type Singleton struct {
	count int
}

var instance *Singleton

func init() {
	instance = &Singleton{}
}

func GetInstance() *Singleton {
	if instance == nil {
		instance = new(Singleton)
	}

	return instance
}

func (s *Singleton) AddOne() int {
	s.count++
	return s.count
}

我們來分析一下這段代碼的差別,在 Java 或 C++ 語言中,變量實例會在程序開始時被初始化為 NULL。 但在 Go 中,你可以將結構的指針初始化為 nil,但不能將一個結構初始化為 nil (相當于其他語言的 NULL)。

所以 var instance *singleton* 這一語句定義了一個指向結構的指針為 nil ,而變量稱為 instance。

我們創(chuàng)建了一個 GetInstance 方法,檢查實例是否已經被初始化(instance == nil),并在已經分配的空間中創(chuàng)建一個實例 instance = new(singleton)

Addone() 方法將獲取變量實例的計數(shù),并逐個加 1,然后返回當前計數(shù)器的值。

再一次運行單元測試代碼:

$ go test -v -run=GetInstance .
=== RUN   TestGetInstance
--- PASS: TestGetInstance (0.00s)
PASS
ok      github.com/yuzhoustayhungry/GoDesignPattern/singleton   0.297s

單例模式優(yōu)缺點

優(yōu)點:

  • 你可以保證一個類只有一個實例。
  • 你獲得了一個指向該實例的全局訪問節(jié)點。
  • 僅在首次請求單例對象時對其進行初始化。

缺點:

  • 違反了單一職責原則。 該模式同時解決了兩個問題。
  • 單例模式可能掩蓋不良設計, 比如程序各組件之間相互了解過多等。
  • 該模式在多線程環(huán)境下需要進行特殊處理, 避免多個線程多次創(chuàng)建單例對象。
  • 單例的客戶端代碼單元測試可能會比較困難, 因為許多測試框架以基于繼承的方式創(chuàng)建模擬對象。 由于單例類的構造函數(shù)是私有的, 而且絕大部分語言無法重寫靜態(tài)方法, 所以你需要想出仔細考慮模擬單例的方法。 要么干脆不編寫測試代碼, 或者不使用單例模式。

以上就是詳解Go語言設計模式之單例模式的詳細內容,更多關于Go語言 單例模式的資料請關注腳本之家其它相關文章!

相關文章

  • GORM中Model和Table的區(qū)別及使用

    GORM中Model和Table的區(qū)別及使用

    Model?和Table是兩種與數(shù)據庫表交互的核心方法,但它們的用途和行為存在著差異,本文主要介紹了GORM中Model和Table的區(qū)別及使用,具有一定的參考價值,感興趣的可以了解一下
    2025-03-03
  • Golang使用Gin框架實現(xiàn)路由分類處理請求流程詳解

    Golang使用Gin框架實現(xiàn)路由分類處理請求流程詳解

    Gin是一個golang的微框架,封裝比較優(yōu)雅,具有快速靈活,容錯方便等特點,這篇文章主要介紹了Golang使用Gin框架實現(xiàn)路由分類處理請求,感興趣的同學可以參考下文
    2023-05-05
  • 使用Golang打印特定的日期時間的操作

    使用Golang打印特定的日期時間的操作

    這篇文章主要給大家詳細介紹了如何使用Golang打印特定的日期時間的操作,文中有詳細的代碼示例,具有一定的參考價值,需要的朋友可以參考下
    2023-07-07
  • Go?for-range?的?value值地址每次都一樣的原因解析

    Go?for-range?的?value值地址每次都一樣的原因解析

    循環(huán)語句是一種常用的控制結構,在?Go?語言中,除了?for?關鍵字以外,還有一個?range?關鍵字,可以使用?for-range?循環(huán)迭代數(shù)組、切片、字符串、map?和?channel?這些數(shù)據類型,這篇文章主要介紹了Go?for-range?的?value值地址每次都一樣的原因解析,需要的朋友可以參考下
    2023-05-05
  • Go1.21新增slices包的用法詳解

    Go1.21新增slices包的用法詳解

    Go?1.21新增的?slices?包提供了很多和切片相關的函數(shù),可以用于任何類型的切片,這篇文章主要來和大家介紹一下slices包中相關函數(shù)的用法,需要的可以參考一下
    2023-08-08
  • go如何優(yōu)雅關閉Graceful?Shutdown服務

    go如何優(yōu)雅關閉Graceful?Shutdown服務

    這篇文章主要為大家介紹了go優(yōu)雅關閉Graceful?Shutdown服務詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-05-05
  • 解決go build不去vendor下查找包的問題

    解決go build不去vendor下查找包的問題

    這篇文章主要介紹了解決go build不去vendor下查找包的問題,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • 深入探索Go語言中unsafe包的使用

    深入探索Go語言中unsafe包的使用

    Go語言的unsafe包被譽為黑科技,它為Go語言提供了底層訪問和操控內存的能力,本文將深入探討Go語言中unsafe包的使用方法和注意事項,需要的可以參考一下
    2023-04-04
  • Go語言dolphinscheduler任務調度處理

    Go語言dolphinscheduler任務調度處理

    這篇文章主要為大家介紹了Go語言dolphinscheduler任務調度處理,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-06-06
  • Go語言中常量定義方法實例分析

    Go語言中常量定義方法實例分析

    這篇文章主要介紹了Go語言中常量定義方法,以實例形式分析了Go語言中常量的定義及使用技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02

最新評論