Golang基于sync.Once實(shí)現(xiàn)單例的操作代碼
在go里實(shí)現(xiàn)單例模式有多種方式:
- 基于lock
- 基于init函數(shù)
- 基于sync.Once
本文介紹基于sync.Once的方式來實(shí)現(xiàn)單例,熟練掌握這種模式,并理解其底層原理,對(duì)大部分人來講已經(jīng)完全夠用了。
基于sync.Once實(shí)現(xiàn)單例
// 其他package也可見,在其他地方也可以new新對(duì)象 // 但是最終調(diào)用Conn()方法時(shí),都是用的single這個(gè)單例 // 1 type Driver struct { // 小寫字母開頭,外部不可訪問,所以new個(gè)Driver新對(duì)象也沒用 // 2 conn string } // 全局變量,指針默認(rèn)值為nil // 3 var single *Driver // 單例 var once sync.Once // 對(duì)外暴露的公共方法 func (s *Driver) Conn() { fmt.Printf("conn=%s", single.conn) // do something } // 4 func GetDriverSingleton() *Driver { // 對(duì)GetDriverSingleton()方法的調(diào)用,都會(huì)執(zhí)行once.Do()方法,只不過參數(shù)func()只會(huì)被執(zhí)行一次 // 若并發(fā)執(zhí)行once.Do(),多個(gè)協(xié)程會(huì)阻塞,因內(nèi)部是通過Mutex來控制 once.Do(func() { single = new(Driver) single.conn = "single conn" time.Sleep(50 * time.Millisecond) }) return single }
單例類型定義Driver
Driver類的方法要支持跨包訪問,因此需要以大寫字母開頭。
小寫字母開頭,作用域僅限于包內(nèi)部。
類Field conn
類變量conn需要小寫字母開頭,跨包不可訪問,避免在包外被修改。
但是包內(nèi)還是有可能被修改。
once.Do(func() {})
每次調(diào)用GetDriverSingleton(),都會(huì)調(diào)用once.Do()方法,但是在once.Do()方法內(nèi)部,僅會(huì)執(zhí)行一次參數(shù)func(){},因此就保證了單例唯一初始化。
并發(fā)訪問once.Do()
不會(huì)有并發(fā)訪問問題,因once.Do()內(nèi)部通過mutex來控制。
// once.DO() if atomic.LoadUint32(&o.done) == 0 { // Outlined slow-path to allow inlining of the fast-path. o.doSlow(f) } // doSlow() func (o *Once) doSlow(f func()) { o.m.Lock() // 互斥鎖 defer o.m.Unlock() if o.done == 0 { defer atomic.StoreUint32(&o.done, 1) f() } }
對(duì)外暴露方法Conn()
外部對(duì)Conn()方法的調(diào)用,最終都由單例single來實(shí)現(xiàn)。
重新new(Driver)會(huì)發(fā)生什么?
很遺憾,無法將構(gòu)造函數(shù)改成private,也就是說,在包外部是可以通過new(Driver)來創(chuàng)建新的對(duì)象。
但無論是哪個(gè)對(duì)象,對(duì)公開方法Conn()的調(diào)用,最終都是由單例single來執(zhí)行的。
到此這篇關(guān)于golang實(shí)現(xiàn)單例的操作代碼的文章就介紹到這了,更多相關(guān)go單例內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- Go語言標(biāo)準(zhǔn)庫sync.Once使用場(chǎng)景及性能優(yōu)化詳解
- golang使用sync.Once實(shí)現(xiàn)懶加載的用法和坑點(diǎn)詳解
- golang中sync.Once只執(zhí)行一次的原理解析
- Golang并發(fā)利器sync.Once的用法詳解
- go并發(fā)利器sync.Once使用示例詳解
- go?sync.Once實(shí)現(xiàn)高效單例模式詳解
- 一文解析 Golang sync.Once 用法及原理
- Go并發(fā)編程之sync.Once使用實(shí)例詳解
- Go語言并發(fā)編程 sync.Once
- 深入理解go sync.Once的具體使用
相關(guān)文章
Go標(biāo)準(zhǔn)庫之Requests的介紹與基本使用
Python中的Requests庫非常強(qiáng)大,所以Go開發(fā)者模仿Python的Requests庫,由此誕生了Grequests庫,本文主要介紹了Requests的基本使用,有需要的可以參考下2024-04-04golang http 連接超時(shí)和傳輸超時(shí)的例子
今天小編就為大家分享一篇golang http 連接超時(shí)和傳輸超時(shí)的例子,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧2019-07-07Go語言使用Timeout Context取消任務(wù)的實(shí)現(xiàn)
本文主要介紹了Go語言使用Timeout Context取消任務(wù)的實(shí)現(xiàn),包括基本的任務(wù)取消和控制HTTP客戶端請(qǐng)求的超時(shí),具有一定的參考價(jià)值,感興趣的可以了解一下2024-01-01golang?使用chromedp獲取頁面請(qǐng)求日志network
這篇文章主要為大家介紹了golang?使用chromedp獲取頁面請(qǐng)求日志network方法實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-11-11詳解Go如何優(yōu)雅的對(duì)時(shí)間進(jìn)行格式化
這篇文章主要為大家詳細(xì)介紹了Go語言中是如何優(yōu)雅的對(duì)時(shí)間進(jìn)行格式化的,文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起了解一下2023-06-06