亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

詳解Go語言設(shè)計(jì)模式之單例模式

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

單例模式的概念

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

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

單例模式結(jié)構(gòu)

單例模式的使用場景

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

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

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

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

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

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

在這個(gè)場景下,我們需要有 3 個(gè)測試來堅(jiān)持我們的單元測試。

第一個(gè)單元測試

與 Java 或 C++ 這種面向?qū)ο笳Z言中不同,Go 實(shí)現(xiàn)單例模式?jīng)]有像靜態(tài)成員的東西(通過 static 修飾),但是可以通過包的范圍來提供一個(gè)類似的功能。

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

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
}

然后,我們通過編寫測試代碼來驗(yàn)證我們聲明的函數(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)
	}
}

第一個(gè)測試是檢查是顯而易見,但在復(fù)雜的應(yīng)用中,其重要性也不小。當(dāng)我們要求獲得一個(gè)計(jì)數(shù)器的實(shí)例時(shí),我們實(shí)際上需要得到一個(gè)結(jié)果。

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

	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)

	}

運(yùn)行上面的代碼:

$ 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

單例模式實(shí)現(xiàn)

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

在 Go 中,沒有 static 這個(gè)關(guān)鍵字,但是我們可以通過使用包的范圍來達(dá)到同樣的效果。

首先,我們創(chuàng)建一個(gè)結(jié)構(gòu)體,其中包含我們想要保證的對象 在程序執(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++ 語言中,變量實(shí)例會(huì)在程序開始時(shí)被初始化為 NULL。 但在 Go 中,你可以將結(jié)構(gòu)的指針初始化為 nil,但不能將一個(gè)結(jié)構(gòu)初始化為 nil (相當(dāng)于其他語言的 NULL)。

所以 var instance *singleton* 這一語句定義了一個(gè)指向結(jié)構(gòu)的指針為 nil ,而變量稱為 instance。

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

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

再一次運(yùn)行單元測試代碼:

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

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

優(yōu)點(diǎn):

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

缺點(diǎn):

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

以上就是詳解Go語言設(shè)計(jì)模式之單例模式的詳細(xì)內(nèi)容,更多關(guān)于Go語言 單例模式的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • golang中protobuf的使用詳解

    golang中protobuf的使用詳解

    protobuf是Google公司提出的一種輕便高效的結(jié)構(gòu)化數(shù)據(jù)存儲(chǔ)格式,常用于結(jié)構(gòu)化數(shù)據(jù)的序列化,具有語言無關(guān)、平臺(tái)無關(guān)、可擴(kuò)展性特性,常用于通訊協(xié)議、服務(wù)端數(shù)據(jù)交換場景,下面我們就來看看golang中protobuf的具體使用吧
    2023-10-10
  • Go-RESTful實(shí)現(xiàn)下載功能思路詳解

    Go-RESTful實(shí)現(xiàn)下載功能思路詳解

    這篇文章主要介紹了Go-RESTful實(shí)現(xiàn)下載功能,文件下載包括文件系統(tǒng)IO和網(wǎng)絡(luò)IO,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10
  • Go語言中的定時(shí)器原理與實(shí)戰(zhàn)應(yīng)用

    Go語言中的定時(shí)器原理與實(shí)戰(zhàn)應(yīng)用

    在Go語言中,Timer和Ticker是處理定時(shí)任務(wù)的重要工具,Timer用于一次性事件,而Ticker則用于周期性事件,本文詳細(xì)介紹了這兩種定時(shí)器的創(chuàng)建、使用和停止方法,并通過實(shí)際案例展示了它們在監(jiān)控日志、檢查系統(tǒng)狀態(tài)等方面的應(yīng)用
    2024-10-10
  • GO語言實(shí)現(xiàn)的端口掃描器分享

    GO語言實(shí)現(xiàn)的端口掃描器分享

    這篇文章主要介紹了GO語言實(shí)現(xiàn)的端口掃描器分享,本文直接給出實(shí)現(xiàn)代碼,代碼中包含大量注釋,需要的朋友可以參考下
    2014-10-10
  • Golang單元測試與覆蓋率的實(shí)例講解

    Golang單元測試與覆蓋率的實(shí)例講解

    這篇文章主要介紹了Golang單元測試與覆蓋率的實(shí)例講解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-11-11
  • 解決golang編譯提示dial tcp 172.217.160.113:443: connectex: A connection attempt failed(推薦)

    解決golang編譯提示dial tcp 172.217.160.113:443: con

    這篇文章主要介紹了解決golang編譯提示dial tcp 172.217.160.113:443: connectex: A connection attempt failed,此問題完美解決,需要的朋友可以參考下
    2023-02-02
  • Linux中Go環(huán)境配置和GoModule常用操作

    Linux中Go環(huán)境配置和GoModule常用操作

    這篇文章主要介紹了Linux中Go環(huán)境配置和GoModule,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-01-01
  • 解決panic: assignment to entry in nil map問題

    解決panic: assignment to entry in nil

    這篇文章主要介紹了解決panic: assignment to entry in nil map問題,具有很好的參考價(jià)值,希望對大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2008-01-01
  • 通過Go channel批量讀取數(shù)據(jù)的示例詳解

    通過Go channel批量讀取數(shù)據(jù)的示例詳解

    批量處理的主要邏輯是:從 channel 中接收數(shù)據(jù),積累到一定數(shù)量或者達(dá)到時(shí)間限制后,將數(shù)據(jù)批量處理(例如發(fā)送到 Kafka 或者寫入網(wǎng)絡(luò)),下面我將展示一個(gè)從 Go channel 中批量讀取數(shù)據(jù),并批量發(fā)送到 Kafka 和批量寫入網(wǎng)絡(luò)數(shù)據(jù)的示例,需要的朋友可以參考下
    2024-10-10
  • Go語言切片前或中間插入項(xiàng)與內(nèi)置copy()函數(shù)詳解

    Go語言切片前或中間插入項(xiàng)與內(nèi)置copy()函數(shù)詳解

    這篇文章主要介紹了Go語言切片前或中間插入項(xiàng)與內(nèi)置copy()函數(shù)詳解,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-04-04

最新評論