成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

Rust 1.80后如何使用延遲初始化模式?

開發(fā) 前端
與lazy_static和once_cell這兩種crate相比,標(biāo)準(zhǔn)庫提供的延遲初始化類型的一大優(yōu)點(diǎn)是不需要任何額外的依賴項(xiàng)。盡管這兩個(gè)crate本身只有幾個(gè)依賴項(xiàng),但這仍然意味著你的項(xiàng)目將有更多的依賴項(xiàng),并且需要更多的編譯時(shí)間。

在應(yīng)用程序開始時(shí)最常見的事情之一是初始化各種資源。這可以是應(yīng)用程序配置、日志服務(wù)或某些數(shù)據(jù)庫連接。然而,并非所有這些都需要在應(yīng)用開始時(shí)就準(zhǔn)備好,因?yàn)檫@可能會(huì)導(dǎo)致啟動(dòng)緩慢。

這就需要在使用資源的時(shí)候再進(jìn)行初始化,延遲初始化模式可以幫助我們推遲資源的初始化。如果資源根本不使用,也可以完全跳過初始化。

在Rust的舊版本中,其標(biāo)準(zhǔn)庫不支持這種延遲初始化。在生態(tài)系統(tǒng)中有幾個(gè)流行的crate通常用于此功能,例如lazy_static和once_cell。從Rust 1.80開始,這些crate提供的許多功能現(xiàn)在可以在標(biāo)準(zhǔn)庫中使用,并且可以用來代替這兩個(gè)crate。

在這篇文章中,我們將介紹什么是延遲初始化模式,lazy_static和once_cell如何提供延遲初始化的功能,如何使用標(biāo)準(zhǔn)庫進(jìn)行延遲初始化,標(biāo)準(zhǔn)庫與lazy_static和once_cell之間的比較。

延遲初始化模式

考慮一個(gè)示例,我們有一個(gè)不經(jīng)常使用的API接口,需要從磁盤讀取和解析一個(gè)大文件。

我們可以在應(yīng)用程序開始時(shí)執(zhí)行讀取和解析,但是,這可能會(huì)阻止服務(wù)器在解析完成之前提供服務(wù)。還有一種情況是,這個(gè)特定的API接口根本沒有被調(diào)用,因此用于加載文件的資源是沒有用的。

另一個(gè)例子是,如果應(yīng)用程序使用一些內(nèi)存DB,如sqlite或redis。但是,實(shí)際上并非應(yīng)用程序的所有調(diào)用都需要數(shù)據(jù)庫。在這種情況下,將DB加載到內(nèi)存中并每次維護(hù)連接開銷是沒必要的。

我們可以將這些資源的初始化推遲到需要的時(shí)候,在第一次使用時(shí)初始化它們,并保留它們以供以后使用,這種模式被稱為延遲初始化模式。

然而,這在Rust中出現(xiàn)了一個(gè)小問題,我們必須將延遲初始化的資源作為參數(shù)傳遞給每個(gè)函數(shù),或者將其設(shè)置為靜態(tài)全局的,并在運(yùn)行時(shí)使用unsafe的Rust代碼對(duì)其進(jìn)行初始化。

為了避免這種情況,像lazy_static或once_cell這樣的crate為不安全的操作提供了安全的封裝,我們可以使用它們?cè)诖a中安全地使用延遲初始化的值。

lazy_static和once_cell如何提供延遲初始化

lazy_static提供了一個(gè)宏來編寫靜態(tài)變量的初始化代碼,并且在運(yùn)行時(shí)第一次使用時(shí)初始化變量。一般語法是:

use lazy_static::lazy_static;
lazy_static!{
  static ref VAR : TYPE = {initialization code}
}

例如,將日志級(jí)別設(shè)置為靜態(tài)變量,如下所示:

use lazy_static::lazy_static;

lazy_static! {
    static ref LOG_LEVEL: String = get_log_level();
}

fn get_log_level() -> String {
    match std::env::var("LOG_LEVEL") {
        Ok(s) => s,
        Err(_) => "WARN".to_string(),
    }
}

fn main() {
    println!("{}", *LOG_LEVEL);
}

lazy_static!宏定義在運(yùn)行時(shí)使用get_log_level函數(shù)來設(shè)置日志級(jí)別。

雖然這很簡單,但它也有一些自己的問題。我們必須使用靜態(tài)ref,這不是一個(gè)有效的Rust語法,我們需要取消對(duì)LOG_LEVEL的引用,以便在println語句中使用。

我們可以使用once_cellcrate做同樣的事情:

use once_cell::sync::OnceCell;

static LOG_LEVEL: OnceCell<String> = OnceCell::new();

fn get_log_level() -> String {
    match std::env::var("LOG_LEVEL") {
        Ok(s) => s,
        Err(_) => "WARN".to_string(),
    }
}

fn main() {
    let log_level = LOG_LEVEL.get_or_init(get_log_level);
    println!("{}", log_level);
}

在這里,我們沒有在聲明中指定代碼,而是在需要獲取值時(shí)使用了get_or_init方法。

如果值未初始化,則使用給定函數(shù)初始化該值,否則將返回現(xiàn)有值。因?yàn)槲覀冎苯荧@取值,所以不需要任何額外的解引用操作。

雖然這兩種方法各有優(yōu)缺點(diǎn),但是需要在依賴項(xiàng)中再添加一個(gè)外部crate。Rust 1.80后的標(biāo)準(zhǔn)庫提供了延遲初始化的類型,我們就可以直接使用這些類型,從而減少依賴項(xiàng)的數(shù)量。

使用標(biāo)準(zhǔn)庫進(jìn)行延遲初始化

在Rust 1.80后,類似lazy_static和once_cell的延遲初始化類型已經(jīng)在Rust標(biāo)準(zhǔn)庫中穩(wěn)定下來了。我們可以使用它們代替任何外部crate來實(shí)現(xiàn)類似的功能。

標(biāo)準(zhǔn)庫中的OnceLock類型可以類似于once_cellcrate的OnceCell類型使用:

use std::sync::OnceLock;

static LOG_LEVEL: OnceLock<String> = OnceLock::new();

fn get_log_level() -> String {
    match std::env::var("LOG_LEVEL") {
        Ok(s) => s,
        Err(_) => "WARN".to_string(),
    }
}

fn main() {
    let log_level = LOG_LEVEL.get_or_init(get_log_level);
    println!("{}", log_level);
}

與once_cell的例子相比,我們用OnceLock代替了OnceCell,但其余的代碼仍然是相同的。OnceLock類型還公開了一個(gè)名為get_or_init的方法,該方法提供了與OnceCell的get_or_init相同的功能。

與lazy_static相比,我們可以使用LazyLock類型在聲明級(jí)別指定初始化函數(shù),而不必使用宏:

use std::sync::LazyLock;

static LOG_LEVEL: LazyLock<String> = LazyLock::new(get_log_level);

fn get_log_level() -> String {
    match std::env::var("LOG_LEVEL") {
        Ok(s) => s,
        Err(_) => "WARN".to_string(),
    }
}

fn main() {
    println!("{}", *LOG_LEVEL);
}

這里我們傳遞一個(gè)初始化函數(shù)給LazyLock的new方法,當(dāng)變量的值第一次被訪問時(shí),類型內(nèi)部調(diào)用這個(gè)函數(shù)來初始化這個(gè)值。

標(biāo)準(zhǔn)庫與lazy_static和once_cell之間的比較

與lazy_static和once_cell這兩種crate相比,標(biāo)準(zhǔn)庫提供的延遲初始化類型的一大優(yōu)點(diǎn)是不需要任何額外的依賴項(xiàng)。盡管這兩個(gè)crate本身只有幾個(gè)依賴項(xiàng),但這仍然意味著你的項(xiàng)目將有更多的依賴項(xiàng),并且需要更多的編譯時(shí)間。

標(biāo)準(zhǔn)庫提供的延遲初始化類型的另一個(gè)優(yōu)點(diǎn)是它們是由官方rust標(biāo)準(zhǔn)庫團(tuán)隊(duì)直接開發(fā)和維護(hù)的。

總結(jié)

將lazy_static初始化類型引入Rust標(biāo)準(zhǔn)庫本身,為在代碼中使用延遲初始化提供了很多便利,而無需添加另一個(gè)crate作為依賴項(xiàng)。

有了這些類型,我們就可以只在需要的時(shí)候進(jìn)行昂貴的計(jì)算,并且只初始化一次昂貴的結(jié)構(gòu),比如正則表達(dá)式,而不必每次都手工進(jìn)行初始化檢查。

相信隨著時(shí)間的推移,我們會(huì)看到更多項(xiàng)目使用標(biāo)準(zhǔn)庫中的延遲初始化類型,而不是在新創(chuàng)建的項(xiàng)目中引入外部crate。

責(zé)任編輯:武曉燕 來源: coding到燈火闌珊
相關(guān)推薦

2016-11-11 00:33:25

雙重檢查鎖定延遲初始化線程

2022-07-27 08:56:29

Go程序多版本

2023-11-12 23:08:17

C++初始化

2010-03-11 19:25:35

Python環(huán)境

2010-03-25 14:42:33

2009-09-02 16:52:55

C#數(shù)組初始化

2009-09-07 09:24:26

2025-02-13 11:11:53

Redis哨兵代碼

2019-11-04 13:50:36

Java數(shù)組編程語言

2009-09-08 09:48:34

LINQ初始化數(shù)組

2009-11-11 15:29:15

ADO初始化

2011-06-17 15:29:44

C#對(duì)象初始化器集合初始化器

2010-07-28 10:22:33

FlexApplica

2021-03-12 10:30:11

SpringMVC流程初始化

2022-07-06 10:37:45

SpringServlet初始化

2020-12-03 09:50:52

容器IoC流程

2024-01-15 06:34:09

Gin鏡像容器

2010-02-05 17:16:05

C++構(gòu)造函數(shù)

2009-02-13 10:33:00

交換機(jī)初始化配置

2009-12-16 14:04:04

Ruby對(duì)象初始化
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 日韩一区二区三区视频 | 久久久精品国产 | 午夜免费精品视频 | 在线播放精品视频 | 精品乱人伦一区二区三区 | 精品福利在线 | 天天干天天插天天 | 成人无遮挡毛片免费看 | 久久久日韩精品一区二区三区 | 91视频久久 | 国产一区二 | 国产亚洲精品美女久久久久久久久久 | 天天拍天天操 | 午夜免费电影院 | 欧美久久精品一级黑人c片 91免费在线视频 | 久久精品国产一区二区电影 | 色资源在线观看 | 久久久久国产 | 久久9久 | 理伦毛片 | 一级黄色av电影 | 日韩波多野结衣 | 国产精品久久久久久久久污网站 | 欧美亚洲国语精品一区二区 | 日批的视频 | 亚洲视频在线观看 | aaaaaa大片免费看最大的 | 99久久婷婷国产综合精品电影 | 亚洲国产成人av好男人在线观看 | 四虎影视一区二区 | 国产精品久久国产精品 | 久久精品视频免费看 | 粉嫩av在线 | 色网站视频 | 亚洲精品第一国产综合野 | 国产伊人精品 | 五月婷婷激情 | 精品久久久久一区二区国产 | www.欧美视频 | 日韩免费视频 | 精品免费国产视频 |