定数
遅延評価される定数を宣言する
遅延評価される定数 HashMap を宣言します。HashMap は
一度だけ評価され、グローバルな static 参照を介して保存されます。
use lazy_static::lazy_static;
use std::collections::HashMap;
lazy_static! {
static ref PRIVILEGES: HashMap<&'static str, Vec<&'static str>> = {
let mut map = HashMap::new();
map.insert("James", vec!["user", "admin"]);
map.insert("Jim", vec!["user"]);
map
};
}
fn show_access(name: &str) {
let access = PRIVILEGES.get(name);
println!("{}: {:?}", name, access);
}
fn main() {
let access = PRIVILEGES.get("James");
println!("James: {:?}", access);
show_access("Jim");
}
Std:cell
OnceCell は代替手段として標準ライブラリに含まれています。
use std::cell::OnceCell;
fn main() {
let cell = OnceCell::new();
assert!(cell.get().is_none());
let value: &String = cell.get_or_init(|| {
"Hello, World!".to_string()
});
assert_eq!(value, "Hello, World!");
assert!(cell.get().is_some());
}
std::cell::LazyCell
LazyCell 型は、値への初回アクセス時までその初期化を遅らせるために使用できます。
これは、スコープの実行全体を通して必要にならない可能性がある高コストな計算に役立ちます。
この例では、LazyCell を使って、ユーザー ID に基づく権限セットを遅延計算します。
static な遅延型とは異なり、LazyCell は周囲のスコープからローカル変数をキャプチャできます。
use std::cell::LazyCell;
fn main() {
let user_id = 42;
// クロージャはまだ実行されません。
let permissions = LazyCell::new(|| {
println!("--- Fetching permissions from database for ID {} ---", user_id);
// 高コストな操作をシミュレートする
vec!["read".to_string(), "write".to_string()]
});
println!("User {} session started.", user_id);
// 初期化は、permissions を初めてデリファレンスしたときにのみ行われます。
if true { // ここに条件チェックがあると想像してください
println!("Permissions: {:?}", *permissions);
}
// 以降のアクセスでは、すでに初期化済みの値が使用されます。
println!("First permission: {}", permissions[0]);
}
std::sync::LazyLock
LazyLock 型は、static コンテキストで使用できる LazyCell のスレッドセーフ版です。
これは、グローバルで遅延初期化されるデータに対する lazy_static クレートの標準ライブラリ版の代替手段です。
この例では、初回アクセス時に環境から一度だけ読み込まれる
グローバルな設定を作成するために LazyLock をどのように使用するかを示します。
use std::sync::LazyLock;
struct Config {
api_key: String,
timeout: u64,
}
// 最初の使用時に初期化されるグローバル設定。
static APP_CONFIG: LazyLock<Config> = LazyLock::new(|| {
println!("Loading configuration...");
Config {
api_key: std::env::var("API_KEY").unwrap_or_else(|_| "default_key".to_string()),
timeout: 30,
}
});
fn main() {
println!("App started.");
// 初期化はここで行われます。
let timeout = APP_CONFIG.timeout;
println!("Timeout is: {}s", timeout);
println!("API Key is hidden: {}", APP_CONFIG.api_key.len() > 0);
}