<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      使用sync.Once實現(xiàn)高效的單例模式

      1. 簡介

      本文介紹使用sync.Once來實現(xiàn)單例模式,包括單例模式的定義,以及使用sync.Once實現(xiàn)單例模式的示例,同時也比較了其他單例模式的實現(xiàn)。最后以一個開源框架中使用sync.Once實現(xiàn)單例模式的例子來作為結尾。

      2. 基本實現(xiàn)

      2.1 單例模式定義

      單例模式是一種創(chuàng)建型設計模式,它保證一個類只有一個實例,并提供一個全局訪問點來訪問這個實例。在整個應用程序中,所有對于這個類的訪問都將返回同一個實例對象。

      2.2 sync.Once實現(xiàn)單例模式

      下面是一個簡單的示例代碼,使用 sync.Once 實現(xiàn)單例模式:

       package singleton
      
       import "sync"
      
       type singleton struct {
           // 單例對象的狀態(tài)
       }
      
       var (
           instance *singleton
           once     sync.Once
       )
      
       func GetInstance() *singleton {
           once.Do(func() {
               instance = &singleton{}
               // 初始化單例對象的狀態(tài)
           })
           return instance
       }
      

      在上面的示例代碼中,我們定義了一個 singleton 結構體表示單例對象的狀態(tài),然后將它的實例作為一個包級別的變量 instance,并使用一個 once 變量來保證 GetInstance 函數(shù)只被執(zhí)行一次。

      GetInstance 函數(shù)中,我們使用 once.Do 方法來執(zhí)行一個初始化單例對象。由于 once.Do 方法是基于原子操作實現(xiàn)的,因此可以保證并發(fā)安全,即使有多個協(xié)程同時調(diào)用 GetInstance 函數(shù),最終也只會創(chuàng)建一個對象。

      2.3 其他方式實現(xiàn)單例模式

      2.3.1 全局變量定義時賦值,實現(xiàn)單例模式

      在 Go 語言中,全局變量會在程序啟動時自動初始化。因此,如果在定義全局變量時給它賦值,則對象的創(chuàng)建也會在程序啟動時完成,可以通過此來實現(xiàn)單例模式,以下是一個示例代碼:

      type MySingleton struct {
          // 字段定義
      }
      
      var mySingletonInstance = &MySingleton{
          // 初始化字段
      }
      
      func GetMySingletonInstance() *MySingleton {
          return mySingletonInstance
      }
      

      在上面的代碼中,我們定義了一個全局變量 mySingletonInstance 并在定義時進行了賦值,從而在程序啟動時完成了對象的創(chuàng)建和初始化。在 GetMySingletonInstance 函數(shù)中,我們可以直接返回全局變量 mySingletonInstance,從而實現(xiàn)單例模式。

      2.3.2 init 函數(shù)實現(xiàn)單例模式

      在 Go 語言中,我們可以使用 init 函數(shù)來實現(xiàn)單例模式。init 函數(shù)是在包被加載時自動執(zhí)行的函數(shù),因此我們可以在其中創(chuàng)建并初始化單例對象,從而保證在程序啟動時就完成對象的創(chuàng)建。以下是一個示例代碼:

      package main
      
      type MySingleton struct {
          // 字段定義
      }
      
      var mySingletonInstance *MySingleton
      
      func init() {
          mySingletonInstance = &MySingleton{
              // 初始化字段
          }
      }
      
      func GetMySingletonInstance() *MySingleton {
          return mySingletonInstance
      }
      

      在上面的代碼中,我們定義了一個包級別的全局變量 mySingletonInstance,并在 init 函數(shù)中創(chuàng)建并初始化了該對象。在 GetMySingletonInstance 函數(shù)中,我們直接返回該全局變量,從而實現(xiàn)單例模式。

      2.3.3 使用互斥鎖實現(xiàn)單例模式

      在 Go 語言中,可以只使用一個互斥鎖來實現(xiàn)單例模式。下面是一個簡單代碼的演示:

      var instance *MySingleton
      var mu sync.Mutex
      
      func GetMySingletonInstance() *MySingleton {
         mu.Lock()
         defer mu.Unlock()
      
         if instance == nil {
            instance = &MySingleton{
               // 初始化字段
            }
         }
         return instance
      }
      

      在上面的代碼中,我們使用了一個全局變量instance來存儲單例對象,并使用了一個互斥鎖 mu 來保證對象的創(chuàng)建和初始化。具體地,我們在 GetMySingletonInstance 函數(shù)中首先加鎖,然后判斷 instance 是否已經(jīng)被創(chuàng)建,如果未被創(chuàng)建,則創(chuàng)建并初始化對象。最后,我們釋放鎖并返回單例對象。

      需要注意的是,在并發(fā)高的情況下,使用一個互斥鎖來實現(xiàn)單例模式可能會導致性能問題。因為在一個 goroutine 獲得鎖并創(chuàng)建對象時,其他的 goroutine 都需要等待,這可能會導致程序變慢。

      2.4 使用sync.Once實現(xiàn)單例模式的優(yōu)點

      相對于init 方法和使用全局變量定義賦值單例模式的實現(xiàn),sync.Once 實現(xiàn)單例模式可以實現(xiàn)延遲初始化,即在第一次使用單例對象時才進行創(chuàng)建和初始化。這可以避免在程序啟動時就進行對象的創(chuàng)建和初始化,以及可能造成的資源的浪費。

      而相對于使用互斥鎖實現(xiàn)單例模式,使用 sync.Once 實現(xiàn)單例模式的優(yōu)點在于更為簡單和高效。sync.Once提供了一個簡單的接口,只需要傳遞一個初始化函數(shù)即可。相比互斥鎖實現(xiàn)方式需要手動處理鎖、判斷等操作,使用起來更加方便。而且使用互斥鎖實現(xiàn)單例模式需要在每次訪問單例對象時進行加鎖和解鎖操作,這會增加額外的開銷。而使用 sync.Once 實現(xiàn)單例模式則可以避免這些開銷,只需要在第一次訪問單例對象時進行一次初始化操作即可。

      但是也不是說sync.Once便適合所有的場景,這個是需要具體情況具體分析的。下面說明sync.Onceinit方法,在哪些場景下使用init更好,在哪些場景下使用sync.Once更好。

      2.5 sync.Once和init方法適用場景

      對于init實現(xiàn)單例,比較適用于在程序啟動時就需要初始化變量的場景。因為init函數(shù)是在程序運行前執(zhí)行的,可以確保變量在程序運行時已經(jīng)被初始化。

      對于需要延遲初始化某些對象,對象被創(chuàng)建出來并不會被馬上使用,或者可能用不到,例如創(chuàng)建數(shù)據(jù)庫連接池等。這時候使用sync.Once就非常合適。它可以保證對象只被初始化一次,并且在需要使用時才會被創(chuàng)建,避免不必要的資源浪費。

      3. gin中單例模式的使用

      3.1 背景

      這里首先需要介紹下gin.Engine, gin.Engine是Gin框架的核心組件,負責處理HTTP請求,路由請求到對應的處理器,處理器可以是中間件、控制器或處理HTTP響應等。每個gin.Engine實例都擁有自己的路由表、中間件棧和其他配置項,通過調(diào)用其方法可以注冊路由、中間件、處理函數(shù)等。

      一個HTTP服務器,只會存在一個對應的gin.Engine實例,其保存了路由映射規(guī)則等內(nèi)容。

      為了簡化開發(fā)者Gin框架的使用,不需要用戶創(chuàng)建gin.Engine實例,便能夠完成路由的注冊等操作,提高代碼的可讀性和可維護性,避免重復代碼的出現(xiàn)。這里對于一些常用的功能,抽取出一些函數(shù)來使用,函數(shù)簽名如下:

      // ginS/gins.go
      // 加載HTML模版文件
      func LoadHTMLGlob(pattern string) {}
      // 注冊POST請求處理器
      func POST(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {}
      // 注冊GET請求處理器
      func GET(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {}
      // 啟動一個HTTP服務器
      func Run(addr ...string) (err error) {}
      // 等等...
      

      接下來需要對這些函數(shù)來進行實現(xiàn)。

      3.2 具體實現(xiàn)

      首先從使用出發(fā),這里使用POST方法/GET方法注冊請求處理器,然后使用Run方法啟動服務器:

      func main() {
         // 注冊url對應的處理器
         POST("/login", func(c *gin.Context) {})
         // 注冊url對應的處理器
         GET("/hello", func(c *gin.Context) {})
         // 啟動服務
         Run(":8080")
      }
      

      這里我們想要的效果,應該是調(diào)用Run方法啟動服務后,往/login路徑發(fā)送請求,此時應該執(zhí)行我們注冊的對應處理器,往/hello路徑發(fā)送請求也是同理。

      所以,這里POST方法,GET方法,Run方法應該都是對同一個gin.Engine 進行操作的,而不是各自使用各自的gin.Engine實例,亦或者每次調(diào)用就創(chuàng)建一個gin.Engine實例。這樣子才能達到我們預想的效果。

      所以,我們需要實現(xiàn)一個方法,獲取gin.Engine實例,每次調(diào)用該方法都是獲取到同一個實例,這個其實也就是單例的定義。然后POST方法,GET方法又或者是Run方法,調(diào)用該方法獲取到gin.Engine實例,然后調(diào)用實例去調(diào)用對應的方法,完成url處理器的注冊或者是服務的啟動。這樣子就能夠保證是使用同一個gin.Engine實例了。具體實現(xiàn)如下:

      // ginS/gins.go
      import (
         "github.com/gin-gonic/gin"
      )
      var once sync.Once
      var internalEngine *gin.Engine
      
      func engine() *gin.Engine {
         once.Do(func() {
            internalEngine = gin.Default()
         })
         return internalEngine
      }
      // POST is a shortcut for router.Handle("POST", path, handle)
      func POST(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
         return engine().POST(relativePath, handlers...)
      }
      
      // GET is a shortcut for router.Handle("GET", path, handle)
      func GET(relativePath string, handlers ...gin.HandlerFunc) gin.IRoutes {
         return engine().GET(relativePath, handlers...)
      }
      

      這里engine() 方法使用了 sync.Once 實現(xiàn)單例模式,確保每次調(diào)用該方法返回的都是同一個 gin.Engine 實例。然后POST/GET/Run方法通過該方法獲取到gin.Engine實例,然后調(diào)用實例中對應的方法來完成對應的功能,從而達到POST/GET/Run等方法都是使用同一個實例操作的效果。

      3.3 sync.Once實現(xiàn)單例的好處

      這里想要達到的目的,其實是GET/POST/Run等抽取出來的函數(shù),使用同一個gin.Engine實例。

      為了達到這個目的,我們其實可以在定義internalEngine 變量時,便對其進行賦值;或者是通init函數(shù)完成對internalEngine變量的賦值,其實都可以。

      但是我們抽取出來的函數(shù),用戶并不一定使用,定義時便初始化或者在init方法中便完成了對變量的賦值,用戶沒使用的話,創(chuàng)建出來的gin.Engine實例沒有實際用途,造成了不必要的資源的浪費。

      而engine方法使用sync.Once實現(xiàn)了internalEngin的延遲初始化,只有在真正使用到internalEngine時,才會對其進行初始化,避免了不必要的資源的浪費。

      這里其實也印證了上面我們所說的sync.Once的適用場景,對于不會馬上使用的單例對象,此時可以使用sync.Once來實現(xiàn)。

      4.總結

      單例模式是一種常用的設計模式,用于保證一個類僅有一個實例。在單例模式中,常常使用互斥鎖或者變量賦值的方式來實現(xiàn)單例。然而,使用sync.Once可以更方便地實現(xiàn)單例,同時也能夠避免了不必要的資源浪費。當然,沒有任何一種實現(xiàn)是適合所有場景的,我們需要根據(jù)具體場景具體分析。

      posted @ 2023-03-16 20:02  菜鳥額  閱讀(267)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 免费无码AV一区二区波多野结衣 | 99在线精品国自产拍中文字幕| 亚洲午夜成人精品电影在线观看| 国产精品久久欧美久久一区| 亚洲中文字幕无码不卡电影| 99久久精品国产一区二区| 亚洲AV成人无码久久精品四虎| 高中女无套中出17p| 国产福利萌白酱在线观看视频| 久久夜色精品国产亚av| 成人免费亚洲av在线| 最新中文字幕国产精品| 亚洲欧美中文字幕日韩一区二区| 日日噜噜夜夜狠狠视频| 伊伊人成亚洲综合人网香| 久久精品熟女亚洲av艳妇| 亚洲v欧美v日韩v国产v| 兰溪市| 午夜福利看片在线观看| 亚洲国产欧美在线人成AAAA| 草草线在成年免费视频2| 久久热这里只有精品99| 国产v亚洲v天堂a无码| 熟女女同亚洲女同中文字幕| 东京热一精品无码av| 国产性色的免费视频网站| 国产av丝袜熟女一二三| 亚洲中文字幕在线无码一区二区| 五月婷婷中文字幕| 国产乱妇乱子视频在播放| 自拍第一区视频在线观看| 中文字幕av无码免费一区| 国产伦码精品一区二区| 国产欧亚州美日韩综合区| 日本亚洲一区二区精品久久| 国产成人亚洲精品狼色在线| 亚洲色成人网站www永久四虎| 亚洲精品色一区二区三区| 99riav精品免费视频观看| 久草国产视频| 日本精品成人一区二区三区视频 |