精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

Go Singleton 模式的實現

開發 前端
在日常開發中,我們經常會用到單例模式,比如啟動時創建一個訪問數據庫的客戶端,或者運行時創建一個訪問第三方服務的客戶端。啟動時的單例問題比較簡單,因為不存在并發問題,直接在 main 函數創建即可。

背景

在日常開發中,我們經常會用到單例模式,比如啟動時創建一個訪問數據庫的客戶端,或者運行時創建一個訪問第三方服務的客戶端。啟動時的單例問題比較簡單,因為不存在并發問題,直接在 main 函數創建即可。

package main
func main() {
    Init()
}

var client *Client
func Init() {
    cilent, err = New(...) 
    if err != nil {
        panic(err)
    }
}

如果創建失敗則直接 panic 重新啟動服務。而運行時的單例問題情況有所不同,我們一般會使用 sync.Once 來實現。

var client *Client
var once sync.Once

func GetClient() Client {
    once.Do(func() {
        cilent, err = New(...) 
        if err != nil {
            //
        }
    })
    return client
}

雖然 sync.Once 可以保證并發情況下只執行一次,但是這個只執行一次也會帶來一個問題,那就是如果執行失敗了再也不會再執行了。下面是 go1.24.3 中 sync.Once 的實現。

type Once struct {
    done atomic.Uint32
    m    Mutex
}

func (o *Once) Do(f func()) {
    if o.done.Load() == 0 {
        o.doSlow(f)
    }
}

func (o *Once) doSlow(f func()) {
    o.m.Lock()
    defer o.m.Unlock()
    if o.done.Load() == 0 {
        defer o.done.Store(1)
        f()
    }
}

可以看到不管 f 是否執行成功,Go 都會設置 done 為 1,所以如果 f 創建客戶端失敗,那么后面也不會調用了。但是存在這樣的場景,我們在處理請求時會創建一個單例去做一些事情,但因為這不是關鍵路徑,所以執行失敗時不能 panic,而是返回錯誤并希望下次還能重新走這個流程。所以我們需要實現一個單例模式,每次按需實時獲取,并且可以保證創建失敗時還可以重新執行創建流程。

實現 1

type Singleton[T any] struct {
        mu     sync.Mutex
        loaded bool

        loader func() T
        data   T
}

func (in *Singleton[T]) Get() T {
        in.mu.Lock()
        if !in.loaded && in.loader != nil {
                in.mu.Unlock()
                in.Set(in.loader())
                in.mu.Lock()
        }
        defer in.mu.Unlock()
        return in.data
}

func (in *Singleton[T]) Set(data T) {
        in.mu.Lock()
        defer in.mu.Unlock()
        in.loaded = true
        in.data = data
}

這種方式實現的思路比較清晰簡單,但是性能相對來說不太好,因為第一個創建成功后后續每次獲取時都需要加鎖,如果并發量大的會引起一定時間的代碼阻塞。所以嘗試優化這部分的邏輯。

實現 2

type F[T any] func() (*T, error)

type singleton[T any] struct {
    factory  F[T]
    instance *T
    mutex    sync.Mutex
}

func (s *singleton[T]) Get() (*T, error) {
    if s.instance != nil {
        return s.instance, nil
    }
    s.mutex.Lock()
    defer s.mutex.Unlock()
    if s.instance != nil {
        return s.instance, nil
    }
    result, err := s.factory()
    if err != nil {
        returnnil, err
    }
    s.instance = result
    return result, nil
}

在 Get 的一開始先判斷是否已經創建過了,如果是則直接返回,避免了加鎖,這個看起來解決了問題,但是同時帶來了一個比較隱晦的問題,這種方式無法保證內存可見性,也就是說當讀者看到 s.instance 非空時,不代表 s.instance 指向的實例是完成的,即初始化完成的。看一個例子。

package main

import (
    "fmt"
    "sync"
    "sync/atomic"
)

func main() {
    type MyStruct struct {
        Field int
    }
    for {
        var flag atomic.Bool
        var ptr *MyStruct
        var wg sync.WaitGroup
        wg.Add(2)

        // Goroutine A
        gofunc() {
            defer wg.Done()
            data := &MyStruct{Field: 42}
            ptr = data // 原子操作,但不保證 data 內容立即對其他線程可見
        }()

        // Goroutine B
        gofunc() {
            defer wg.Done()
            if ptr != nil {
                field := ptr.Field
                if field == 0 {
                    fmt.Println(field)
                    flag.Store(true)
                }
            }
        }()
        wg.Wait()
        if flag.Load() {
            println("flag is true")
            break
        }
    }

}

執行上面的代碼,最終會輸出 flag is true,說明 ptr 非空時,ptr.Field 卻是 0。回到單例實現的代碼中測試也是存在類似的問題。

package singleton

import (
    "sync"
    "testing"
)

type Dummy struct {
    Ptr *string
}

func factory() (*Dummy, error) {
    ptr := "test"
    return &Dummy{
        Ptr: &ptr,
    }, nil
}

func TestConcurrent(t *testing.T) {
    for {
        singleton := New(factory)
        var flag bool
        var ptr *Dummy
        var wg sync.WaitGroup
        len := 10
        wg.Add(len)
        for i := 0; i < len; i++ {
            gofunc() {
                defer wg.Done()
                ptr, _ = singleton.Get()
                if ptr.Ptr == nil {
                    flag = true
                }
            }()
        }
        wg.Wait()
        if flag {
            t.Fatal("singleton should not be nil")
        }
    }
}

上面的代碼最終會輸出 singleton should not be nil。說明當 singleton.Get 觀察到 s.instance 非空時 s.instance 指向到單例對象并沒有完成構造。

實現 3

為了實現內存的可見性,我們需要使用 Go 提供的 API。

package singleton

import (
    "sync"
    "sync/atomic"
)

type F[T any] func() (*T, error)

type singleton[T any] struct {
    factory  F[T]
    instance atomic.Pointer[T]
    mutex    sync.Mutex
}

func (s *singleton[T]) Get() (*T, error) {
    if s.instance.Load() != nil {
        return s.instance.Load(), nil
    }
    s.mutex.Lock()
    defer s.mutex.Unlock()
    if s.instance.Load() != nil {
        return s.instance.Load(), nil
    }
    result, err := s.factory()
    if err != nil {
        returnnil, err
    }
    s.instance.Store(result)
    return result, nil
}

上面代碼中,Load 會保證 Store 之前的寫入全部可見,也就是說當 Load 返回非空指針時,Store 寫入的指針以及 s.factory 構造的結構體已經全部同步完成。具體可以參考這里 https://github.com/theanarkh/singleton。

責任編輯:武曉燕 來源: 編程雜技
相關推薦

2009-08-25 18:04:30

C#實現Singlet

2009-07-08 17:25:05

Java Single

2009-07-09 17:30:59

Singleton模式C++ SingletJava Single

2009-08-31 16:12:02

C#使用Singlet

2010-01-07 17:51:36

VB.NET實現Sin

2009-09-02 16:23:27

C# Singleto

2009-08-31 15:48:02

C# Singleto

2012-08-22 10:10:25

單態單態設計設計模式

2011-07-18 16:51:51

Cocoa 單態 模式

2009-08-12 11:40:39

雙檢測鎖定

2009-08-12 13:22:44

Singleton模式

2023-03-27 00:20:48

2021-07-12 10:24:36

Go裝飾器代碼

2023-04-10 09:20:13

設計模式訪客模式

2023-05-04 08:47:31

命令模式抽象接口

2023-05-26 08:41:23

模式Go設計模式

2010-01-21 17:48:25

VB.NET Sing

2023-12-29 08:10:41

Go并發開發

2013-05-28 09:43:38

GoGo語言并發模式

2023-05-15 08:51:46

解釋器模式定義
點贊
收藏

51CTO技術棧公眾號

欧美一区二区三级| 亚洲欧美日韩国产另类专区| 69国产精品成人在线播放| 中文字幕在线播放一区| 欧美aa在线观看| 久久久久久久电影| 成人激情视频免费在线| 久久久久无码国产精品不卡| 婷婷综合一区| 4438x成人网最大色成网站| 狠狠噜天天噜日日噜| 五月激情六月婷婷| 六月丁香综合在线视频| 欧美日韩福利在线观看| av网站免费在线播放| 日韩免费在线电影| 亚洲成人在线免费| 日韩高清三级| 丰满熟女一区二区三区| 日韩成人av影视| 欧美极品欧美精品欧美视频| 国产三级在线观看完整版| 亚洲电影一区| 欧美日韩精品欧美日韩精品一| 加勒比成人在线| 日本在线免费播放| 91蜜桃在线免费视频| 99在线免费观看视频| 丰满人妻一区二区三区四区| 欧美日韩 国产精品| 在线看国产精品| a天堂视频在线观看| 亚洲国产天堂| 欧美亚洲综合一区| 国产一区二区在线视频播放| 国产乱色在线观看| 中文字幕高清不卡| 欧美另类高清视频在线| 欧美一级淫片aaaaaa| 国内精品自线一区二区三区视频| 国产z一区二区三区| 国产精品第56页| 99久久99热这里只有精品| 亚洲美女av网站| 少妇户外露出[11p]| 91麻豆精品国产91久久久久推荐资源| 欧美日本在线看| 九热视频在线观看| 暖暖成人免费视频| 欧美视频在线看| 国产手机免费视频| bl在线肉h视频大尺度| 亚洲精品伦理在线| 欧美xxxx吸乳| 直接在线观看的三级网址| 中文字幕在线观看一区二区| 日韩中文一区| melody高清在线观看| 久久亚洲二区三区| 欧美日韩在线一二三| 青青草观看免费视频在线| 99精品久久99久久久久| 国产午夜精品在线| 姝姝窝人体www聚色窝| 99免费精品在线观看| 国产成人成网站在线播放青青| www.天堂av.com| 大美女一区二区三区| 国产精品一区二区a| 色一情一乱一乱一区91av| 成人sese在线| 蜜桃成人在线| 国产一区二区影视| 国产精品污污网站在线观看 | 日本韩国欧美中文字幕| 亚洲狠狠婷婷| 日本亚洲欧洲色α| 日本视频www色| 久久国产精品一区二区| 91色在线视频| 殴美一级特黄aaaaaa| 97se亚洲国产综合自在线观| 久久另类ts人妖一区二区| 青春草在线观看| 中文字幕乱码日本亚洲一区二区| 亚洲精品国产精品国自产观看| 在线观看精品一区二区三区| 亚洲私人影院在线观看| www.欧美黄色| 日韩伦理精品| 欧美精品色一区二区三区| 潘金莲一级淫片aaaaaaa| 激情视频极品美女日韩| 亚洲视频999| 国产女人被狂躁到高潮小说| 91久久午夜| 国产精品青草久久久久福利99| 国产高清视频免费观看| www国产亚洲精品久久麻豆| 亚洲欧美日韩国产成人综合一二三区| 亚洲性图自拍| 在线观看日韩av先锋影音电影院| 亚洲色图欧美自拍| 欧美一区二区三区久久| www.欧美三级电影.com| 日本三级欧美三级| 久久国产人妖系列| 好吊色欧美一区二区三区四区| 成人免费高清在线播放| 亚洲永久精品国产| 久久精品影视大全| 精品国内亚洲2022精品成人| 日韩在线视频观看| 欧美一级视频免费观看| 精品一区精品二区高清| 久久综合久久久| 3d玉蒲团在线观看| 欧美亚男人的天堂| 欧美无人区码suv| 亚洲网色网站| 国产精品入口夜色视频大尺度| 国产 欧美 精品| 亚洲欧洲精品天堂一级| 欧美黑人经典片免费观看| 祥仔av免费一区二区三区四区| 日韩电影中文 亚洲精品乱码| 久久久久久久久久网站| 麻豆传媒一区二区三区| 久久综合九九| freexxx性亚洲精品| 欧美一区二区视频免费观看| 日本理论中文字幕| 久久aⅴ国产紧身牛仔裤| 粉嫩av免费一区二区三区| 国内外激情在线| 欧美日韩一级二级| 久久精品视频18| 国产日韩欧美一区| 国产精品免费一区二区三区在线观看 | 欧美日韩国产高清一区二区| 免费a级黄色片| 日韩午夜免费| 好吊色欧美一区二区三区 | 日本亚洲不卡| 久久久久久美女| 亚洲欧美黄色片| 亚洲一区在线观看免费观看电影高清| 亚洲va在线va天堂va偷拍| 日本高清免费电影一区| 国产精品第七影院| 国产专区在线| 欧美在线观看一二区| 一级片手机在线观看| 男人的天堂亚洲| 欧美一区二区三区四区五区六区 | 天堂av在线资源| 亚洲超碰精品一区二区| 成人在线观看一区二区| 亚洲无线视频| 国产日韩亚洲精品| 色综合桃花网| 亚洲一区二区福利| 伊人色综合久久久| 亚洲色欲色欲www在线观看| www.色就是色.com| 欧美99在线视频观看| 超碰97网站| 国模私拍一区二区国模曼安| 亚洲美女久久久| 亚洲精品国产精品乱码视色| 国产精品久久久久久亚洲毛片| 奇米视频7777| 亚洲最新色图| 韩国精品一区二区三区六区色诱| 超碰一区二区| 三级精品视频久久久久| а√中文在线资源库| 亚洲五码中文字幕| 88久久精品无码一区二区毛片| 日本aⅴ免费视频一区二区三区| 宅男一区二区三区| 国产成人一二| 国产精品18久久久久久麻辣| 黄色免费网站在线| 亚洲国产精品va在线观看黑人| 亚洲综合久久网| 成人免费在线视频| 麻豆精品国产传媒av| 日韩在线a电影| 激情图片qvod| 欧美男人操女人视频| 国产精品美女免费| 亚洲wwwww| 亚洲性视频网站| 精品人妻一区二区三区蜜桃 | 久久久国产一区二区| 亚洲成人中文字幕在线| 色又黄又爽网站www久久| 亚洲视频重口味| 91在线高清观看| 欧美丝袜在线观看| 久久精品一区| 草草视频在线免费观看| 日本大胆欧美| 久久国产精品久久| 欧美h版在线观看| 日韩av大片在线| 欧美色图天堂| 最近免费中文字幕视频2019| 天堂在线观看视频| 91精选在线观看| 日本中文字幕在线观看视频| 亚洲专区一二三| 来吧亚洲综合网| 久久亚洲精品小早川怜子| 久久久久久无码精品人妻一区二区| 亚洲一区免费| 免费看欧美一级片| 国产精品国内免费一区二区三区| 乱一区二区三区在线播放| 欧美a在线观看| 国产日韩一区在线| 国产日韩另类视频一区| 久久免费国产视频| www在线观看播放免费视频日本| 亚洲天堂男人天堂| 婷婷在线观看视频| 精品国产三级电影在线观看| 国产精品视频第一页| 欧美影院一区二区三区| 国产一级片毛片| 午夜精品久久久久久久久| 一区二区成人免费视频| 国产精品嫩草影院com| 色无极影院亚洲| 久久伊99综合婷婷久久伊| 性色av蜜臀av浪潮av老女人| 国产不卡视频一区| 国产黑丝在线视频| 国产一区二区影院| 亚洲一区二区三区四区精品| 久久99蜜桃精品| 国内外成人免费在线视频| 久久人人97超碰国产公开结果| 欧美在线观看www| 日韩视频中文| 丰满人妻中伦妇伦精品app| 亚洲精品偷拍| 亚洲熟妇av日韩熟妇在线| 亚洲人成毛片在线播放女女| 欧美黄色免费网址| 国产综合久久| 成人午夜视频在线观看免费| 亚洲激情黄色| 毛片在线视频播放| 亚洲一级在线| 免费在线观看毛片网站| 午夜亚洲性色福利视频| 无码人妻丰满熟妇区毛片18| 久久久久久一区二区| av五月天在线| 久久精品国产成人一区二区三区| 日韩在线不卡一区| 国产成人免费在线视频| 9.1在线观看免费| 99精品久久只有精品| 中文字幕一区二区三区人妻不卡| 久久亚洲一区二区三区明星换脸 | 亚洲天堂日韩在线| 日韩av大全| 999久久久精品国产| 六月婷婷激情网| 精品动漫3d一区二区三区免费版| 国产美女主播在线播放 | 国产又大又黄又猛| 久久99精品国产91久久来源| 国产又黄又嫩又滑又白| 久久综合九色综合欧美就去吻 | 特黄特色欧美大片| 日韩免费三级| 综合激情一区| 缅甸午夜性猛交xxxx| 视频一区二区国产| www激情五月| 91亚洲精品久久久蜜桃| 久久免费手机视频| 亚洲精品第1页| 激情视频网站在线观看| 91精品国产综合久久福利| 人妻无码中文字幕免费视频蜜桃| 亚洲午夜未满十八勿入免费观看全集| 日本免费在线视频| 78m国产成人精品视频| 成人国产网站| 国产女主播一区二区三区| 欧美色女视频| 少妇人妻大乳在线视频| 免费观看在线综合色| 中文字幕天堂av| 国产欧美1区2区3区| 日本免费一二三区| 欧美日本乱大交xxxxx| 凸凹人妻人人澡人人添| 久久精品国产清自在天天线| 筱崎爱全乳无删减在线观看| 成人精品一区二区三区| 怕怕欧美视频免费大全| 国产91视频一区| 蜜臀av性久久久久蜜臀aⅴ流畅| 95视频在线观看| 亚洲人成人一区二区在线观看 | aa日韩免费精品视频一| 欧美久久精品一级c片| 欧美图片激情小说| 狠狠久久亚洲欧美| 51妺嘿嘿午夜福利| 亚洲成人av福利| 99久久精品日本一区二区免费 | 最新日本在线观看| 国产精品久久久精品| 欧美日韩一区二区三区不卡视频| 亚洲美女自拍偷拍| 美女在线观看视频一区二区| 亚洲国产精品成人综合久久久| 亚洲美女偷拍久久| 一级黄色录像大片| 国产一区二区黑人欧美xxxx| 日本蜜桃在线观看视频| 成人免费视频网站入口| 国产精品久久久乱弄 | 日本综合字幕| 精品国产一区二区三区麻豆免费观看完整版 | 欧美一区二区三区视频免费| 1区2区3区在线观看| 国产a∨精品一区二区三区不卡| 好吊妞视频这里有精品| 99re8这里只有精品| 精品在线播放免费| 国产男女猛烈无遮挡在线喷水| 欧美日韩一区高清| 国产精品一区二区三区四区色| 欧美专区在线播放| 天堂日韩电影| 免费在线观看的av网站| 91香蕉视频污在线| 麻豆精品久久久久久久99蜜桃| 日韩av在线资源| 自拍偷拍亚洲视频| 麻豆av一区二区三区| 欧美中文字幕| 69精品无码成人久久久久久| 欧美午夜片在线观看| 成人在线播放视频| 国产精品入口日韩视频大尺度 | 粉嫩aⅴ一区二区三区四区| 在线观看成人毛片| 精品第一国产综合精品aⅴ| 青春草免费在线视频| 国产日韩精品推荐| 久久久久久婷| 大地资源高清在线视频观看| 在线电影院国产精品| 高h视频在线观看| 国产99视频精品免费视频36| 亚洲承认在线| 波多野结衣一本| 精品视频在线免费| www视频在线看| 国产伦精品一区二区三区| 国产亚洲福利| 夫妇交换中文字幕| 91精品国产综合久久精品图片 | 视频在线观看免费高清| 亚洲欧洲成人av每日更新| 精品人妻伦一区二区三区久久| 欧美激情精品久久久久久免费印度 | 麻豆传媒免费在线观看| 痴汉一区二区三区| 香蕉精品999视频一区二区| 长河落日免费高清观看| 日韩精品一区二区三区视频| 免费看男女www网站入口在线| 日本成人黄色| 国产精品一区二区免费不卡| 日韩精品久久久久久久酒店| 亚洲精品日韩丝袜精品| 亚洲日本中文| 久久亚洲中文字幕无码| 日本一二三四高清不卡| 99热这里只有精品在线| 日本欧美爱爱爱| 天天揉久久久久亚洲精品| 人妻激情偷乱频一区二区三区| 日本高清不卡aⅴ免费网站| bestiality新另类大全| 免费在线国产精品| 国产成人精品免费在线| 成年人视频免费| 欧美激情在线有限公司| 日韩.com|