最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

go中sync.Once實(shí)現(xiàn)懶加載

 更新時(shí)間:2026年04月07日 10:23:58   作者:諾青235  
本文主要介紹了go中sync.Once實(shí)現(xiàn)懶加載,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

懶加載概念

懶加載(Lazy Loading)是一種延遲初始化技術(shù),核心思想是在真正需要時(shí)才創(chuàng)建或初始化對(duì)象,而不是在程序啟動(dòng)時(shí)就完成所有初始化工作。
核心特征:

  • 延遲初始化:對(duì)象在第一次使用時(shí)才被創(chuàng)建
  • 資源優(yōu)化:避免不必要的資源消耗
  • 啟動(dòng)加速:減少應(yīng)用程序啟動(dòng)時(shí)間
// 傳統(tǒng)初始化 - 啟動(dòng)時(shí)立即執(zhí)行
var db *Database = initDatabase()
// 懶加載 - 使用時(shí)才初始化
var db *Database
var once sync.Once
func GetDB() *Database {
    once.Do(func() {
        db = initDatabase()
    })
    return db
}

適用場(chǎng)景

高成本資源初始化

  • 數(shù)據(jù)庫連接池建立
  • 網(wǎng)絡(luò)連接建立
  • 大型配置文件解析
  • 外部服務(wù)客戶端初始化

sync.Once 原理

sync.Once 是 Go 語言標(biāo)準(zhǔn)庫中提供的一個(gè)確保某個(gè)操作只執(zhí)行一次的并發(fā)原語。其核心設(shè)計(jì)目標(biāo)是在并發(fā)環(huán)境下保證初始化函數(shù)有且僅有一次成功執(zhí)行,同時(shí)保持高性能。
數(shù)據(jù)結(jié)構(gòu)

type Once struct {
    done uint32  // 原子標(biāo)志位
    m    Mutex   // 互斥鎖
}

實(shí)現(xiàn)模式詳解

帶錯(cuò)誤處理的懶加載

type Database struct {
    conn   *sql.DB
    once   sync.Once
    err    error
}
func (db *Database) init() {
    db.conn, db.err = sql.Open("mysql", "user:pass@/dbname")
    if db.err == nil {
        db.err = db.conn.Ping()
    }
}
func (db *Database) GetConnection() (*sql.DB, error) {
    db.once.Do(db.init)
    return db.conn, db.err
}

配置驅(qū)動(dòng)的懶加載
初始化參數(shù)(配置)在運(yùn)行時(shí)動(dòng)態(tài)傳入,懶加載過程依賴外部傳入的配置信息。
特點(diǎn):

  • 配置參數(shù)作為方法參數(shù)傳遞
  • 同一實(shí)例可接受不同配置(但只生效第一次)
  • 更靈活,支持運(yùn)行時(shí)配置
type ConfigClient struct {
    config *Config
    client *Client
    once   sync.Once
    err    error
}
func (c *ConfigClient) lazyInit(config *Config) {
    c.config = config
    c.client, c.err = NewClient(config.Endpoint, config.Timeout)
}
func (c *ConfigClient) GetClient(config *Config) (*Client, error) {
    c.once.Do(func() { c.lazyInit(config) })
    return c.client, c.err
}

適用場(chǎng)景:

  • 依賴外部配置的初始化
  • 動(dòng)態(tài)參數(shù)傳遞
  • 多環(huán)境配置支持

連接驅(qū)動(dòng)的懶加載
配置在實(shí)例創(chuàng)建時(shí)固定,懶加載過程使用預(yù)定義的配置建立連接。
特點(diǎn):

  • 配置在構(gòu)造時(shí)確定
  • 初始化過程完全內(nèi)部化
  • 更穩(wěn)定,配置不可變

問題

func newClientFromConfig() MongoRepository {
    cfg, err := loadConfigFromEnv()  // 在創(chuàng)建時(shí)加載配置
    if err != nil {
        return &mongoClient{err: err}
    }
    return &mongoClient{config: cfg}  // 配置在構(gòu)造時(shí)固定
}
func (c *mongoClient) lazyInit() error {
    c.once.Do(func() {
        // 使用預(yù)先設(shè)置的 c.config,不接收外部參數(shù)
        clientOptions := options.Client().ApplyURI(c.config.URI)
        // ... 使用固定配置建立連接
    })
}

全局單例懶加載

var (
    globalClient *Client
    globalOnce   sync.Once
    globalErr    error
)
func GetGlobalClient() (*Client, error) {
    globalOnce.Do(func() {
        globalClient, globalErr = NewClient()
    })
    return globalClient, globalErr
}

實(shí)際使用

MongoDB 客戶端實(shí)現(xiàn)

package mongo
import (
    "context"
    "sync"
    "time"
    "go.mongodb.org/mongo-driver/mongo"
    "go.mongodb.org/mongo-driver/mongo/options"
)
type Client struct {
    config   *Config
    client   *mongo.Client
    database *mongo.Database
    once     sync.Once
    err      error
}
func NewLazyClient(config *Config) *Client {
    return &Client{config: config}
}
func (c *Client) lazyInit() {
    ctx, cancel := context.WithTimeout(context.Background(), c.config.Timeout)
    defer cancel()
    client, err := mongo.Connect(ctx, options.Client().ApplyURI(c.config.URI))
    if err != nil {
        c.err = err
        return
    }
    // 驗(yàn)證連接
    if err = client.Ping(ctx, nil); err != nil {
        client.Disconnect(context.Background())
        c.err = err
        return
    }
    c.client = client
    c.database = client.Database(c.config.Database)
}
func (c *Client) GetCollection(name string) (*mongo.Collection, error) {
    c.once.Do(c.lazyInit)
    if c.err != nil {
        return nil, c.err
    }
    return c.database.Collection(name), nil
}
// 使用示例
func main() {
    client := NewLazyClient(&Config{
        URI:      "mongodb://localhost:27017",
        Database: "test",
        Timeout:  10 * time.Second,
    })
    // 第一次調(diào)用時(shí)才會(huì)真正建立連接
    collection, err := client.GetCollection("users")
    if err != nil {
        panic(err)
    }
    // 使用 collection...
}

Redis 客戶端實(shí)現(xiàn)

package redis
import (
    "context"
    "sync"
    "time"
    "github.com/redis/go-redis/v9"
)
type LazyClient struct {
    config *RedisConfig
    client redis.UniversalClient
    once   sync.Once
    err    error
}
func (lc *LazyClient) initClient() {
    if len(lc.config.Addrs) == 1 {
        lc.client = redis.NewClient(&redis.Options{
            Addr:     lc.config.Addrs[0],
            Password: lc.config.Password,
            DB:       lc.config.DB,
        })
    } else {
        lc.client = redis.NewClusterClient(&redis.ClusterOptions{
            Addrs:    lc.config.Addrs,
            Password: lc.config.Password,
        })
    }
    // 測(cè)試連接
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    if err := lc.client.Ping(ctx).Err(); err != nil {
        lc.client.Close()
        lc.err = err
    }
}
func (lc *LazyClient) Set(ctx context.Context, key string, value interface{}, expiration time.Duration) error {
    lc.once.Do(lc.initClient)
    if lc.err != nil {
        return lc.err
    }
    return lc.client.Set(ctx, key, value, expiration).Err()
}
func (lc *LazyClient) Get(ctx context.Context, key string) (string, error) {
    lc.once.Do(lc.initClient)
    if lc.err != nil {
        return "", lc.err
    }
    return lc.client.Get(ctx, key).Result()
}

sync.Once 在提供線程安全的同時(shí),保持了優(yōu)異的性能表現(xiàn),是 Go 語言中實(shí)現(xiàn)懶加載的首選方案。

到此這篇關(guān)于go中sync.Once實(shí)現(xiàn)懶加載的文章就介紹到這了,更多相關(guān)go sync.Once懶加載內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • golang變量uint、int大小溢出后的結(jié)果方式

    golang變量uint、int大小溢出后的結(jié)果方式

    在Go語言中,變量的大小溢出后,`uint`類型會(huì)回繞到最小值,而`int`類型會(huì)回繞到最大值的相反數(shù),例如,`uint8`溢出后會(huì)變成0,`int64`溢出后會(huì)變成最小的負(fù)數(shù)
    2024-12-12
  • 關(guān)于go語言編碼需要放到src 文件夾下的問題

    關(guān)于go語言編碼需要放到src 文件夾下的問題

    這篇文章主要介紹了go語言編碼需要放到src 文件夾下的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10
  • Go中RPC遠(yuǎn)程過程調(diào)用的實(shí)現(xiàn)

    Go中RPC遠(yuǎn)程過程調(diào)用的實(shí)現(xiàn)

    本文主要介紹了Go中RPC遠(yuǎn)程過程調(diào)用的實(shí)現(xiàn),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • Golang設(shè)計(jì)模式之責(zé)任鏈模式講解和代碼示例

    Golang設(shè)計(jì)模式之責(zé)任鏈模式講解和代碼示例

    責(zé)任鏈?zhǔn)且环N行為設(shè)計(jì)模式, 允許你將請(qǐng)求沿著處理者鏈進(jìn)行發(fā)送, 直至其中一個(gè)處理者對(duì)其進(jìn)行處理,本文就詳細(xì)給大家介紹一下Golang 責(zé)任鏈模式,文中有詳細(xì)的代碼示例,需要的朋友可以參考下
    2023-06-06
  • Go語言如何利用Mutex保障數(shù)據(jù)讀寫正確

    Go語言如何利用Mutex保障數(shù)據(jù)讀寫正確

    這篇文章主要介紹了互斥鎖的實(shí)現(xiàn)機(jī)制,以及?Go?標(biāo)準(zhǔn)庫的互斥鎖?Mutex?的基本使用方法,文中的示例代碼講解詳細(xì),需要的小伙伴可以參考一下
    2023-05-05
  • Go語言開發(fā)區(qū)塊鏈只需180行代碼(推薦)

    Go語言開發(fā)區(qū)塊鏈只需180行代碼(推薦)

    這篇文章主要介紹了Go語言開發(fā)區(qū)塊鏈只需180行代碼,文章中將不會(huì)涉及工作量證明算法(PoW)以及權(quán)益證明算法(PoS)這類的共識(shí)算法。需要的朋友可以參考下
    2018-05-05
  • 使用Go語言解決Scan空格結(jié)束輸入問題

    使用Go語言解決Scan空格結(jié)束輸入問題

    這篇文章主要為大家介紹了使用Go語言來解決Scan空格結(jié)束輸入問題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步
    2021-11-11
  • omitempty在go中的使用方式

    omitempty在go中的使用方式

    在Go語言編程中,`omitempty`標(biāo)記用于JSON編解碼過程中控制字段是否被包含,當(dāng)結(jié)構(gòu)體字段標(biāo)記為`omitempty`且字段值為空時(shí),該字段不會(huì)出現(xiàn)在生成的JSON中,有助于優(yōu)化JSON結(jié)構(gòu)和減小數(shù)據(jù)體積,通過具體示例解釋了`omitempty`的工作機(jī)制和實(shí)際效果
    2024-09-09
  • golang實(shí)現(xiàn)無鎖隊(duì)列的三種方式

    golang實(shí)現(xiàn)無鎖隊(duì)列的三種方式

    本文主要介紹了golang實(shí)現(xiàn)無鎖隊(duì)列的三種方式,包括基于CAS操作的簡(jiǎn)單有界隊(duì)列、Michael-Scott算法的無鎖鏈表隊(duì)列及Go簡(jiǎn)化指針操作方法,感興趣的可以了解一下
    2026-04-04
  • Golang HTTP 服務(wù)平滑重啟及升級(jí)的思路

    Golang HTTP 服務(wù)平滑重啟及升級(jí)的思路

    Golang HTTP服務(wù)在上線時(shí),需要重新編譯可執(zhí)行文件,關(guān)閉正在運(yùn)行的進(jìn)程,然后再啟動(dòng)新的運(yùn)行進(jìn)程。這篇文章主要介紹了Golang HTTP 服務(wù)平滑重啟及升級(jí),需要的朋友可以參考下
    2020-04-04

最新評(píng)論

绥宁县| 塔河县| 左贡县| 勐海县| 普安县| 库车县| 湘阴县| 务川| 阳朔县| 林甸县| 汶川县| 扎兰屯市| 上蔡县| 藁城市| 青州市| 南部县| 包头市| 永善县| 光泽县| 乌鲁木齐县| 清新县| 铜梁县| 和政县| 固安县| 怀宁县| 高唐县| 新余市| 锦州市| 阳曲县| 葵青区| 南充市| 万安县| 盘山县| 西安市| 宁强县| 比如县| 洛浦县| 嘉兴市| 天镇县| 政和县| 丹凤县|