Устал от lazy_static? Rust 1.80 имеет более чистый путь

Устал от lazy_static? Rust 1.80 имеет более чистый путь

6 июня 2025 г.

Rust предлагает разные способы инициализацииСкомпилируйте время инициализированопеременные. Недавно мне пришлось создать инициализованную переменную выполнения: существующие подходы не работают в этом случае. Я хочу описать несколько способов достичь этого в этом посте.

Константы

Язык ржавчины позволяет создавать константы. Доступны два ключевых слова:constиstaticПолем

Иногда определенное значение используется много раз во всей программе, и копировать его снова и снова может стать неудобным. Более того, не всегда возможно или желательно сделать его переменной, которая переносится на каждую функцию, которая в ней нуждается. В этих случаяхconstКлючевое слово предоставляет удобную альтернативу дублированию кода:

const THING: u32 = 0xABAD1DEA;

let foo = 123 + THING;

-Ключевое слово const

Статический элемент - это значение, которое действителен на всю продолжительность вашей программы ('staticпродолжительность жизни).

На поверхности,staticПредметы кажутся очень похожими наconst: Оба содержат значение, оба требуют аннотации типа, и оба могут быть инициализированы только с постоянными функциями и значениями. Однако,staticзаметно отличаются тем, что они представляют место в памяти. Это означает, что у вас могут быть ссылки наstaticПредметы и потенциально даже изменяют их, делая их по существу глобальные переменные.

Статические элементы не звонятdropВ конце программы.

Есть два типаstaticПредметы: те, которые объявляются в связи сmutКлючевое слово и те, кто без.

-Ключевое слово статичное

Ни один из вышеперечисленных не работает сstructПолем

Я исправил:https://www.reddit.com/r/rust/comments/1l0uwzy/comment/mvgghb0/Полем

const REGEXP_WAREHOUSE_ENDPOINT: Regex = Regex::new(r"^WAREHOUSE__(?<index>\d)__ENDPOINT.*").unwrap();

Попытка составить предыдущую строку возвращает следующую:

error[E0015]: cannot call non-const fn `regex::Regex::new` in constants
  |
6 | const REGEXP_WAREHOUSE_ENDPOINT: Regex = Regex::new(r"^WAREHOUSE__(?<index>\d)__ENDPOINT.*").unwrap();
  |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: calls in constants are limited to constant functions, tuple structs and tuple variants

То же самое происходит, если мы изменимсяconstкstaticПолем

error[E0015]: cannot call non-const fn `regex::Regex::new` in statics
 --> src/config.rs:6:43
  |
6 | static REGEXP_WAREHOUSE_ENDPOINT: Regex = Regex::new(r"^WAREHOUSE__(?<index>\d)__ENDPOINT.*").unwrap();
  |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  |
  = note: calls in statics are limited to constant functions, tuple structs and tuple variants

Нам нуженВремя выполнения инициализированопеременная дляstructПолем Ни одинconstниlazyработа; Время искать что -то другое.

Аlazy_staticящик

Когда вам что -то нужно, есть высокая вероятность того, что кто -то нуждается в этом раньше. Если повезет, они создали для этого ящик. Показательный примерlazy_staticЯщик обеспечивает решение.

Макрос для объявления лениво оцениваемой статики в ржавчине.

Используя этот макрос, можно иметь статику, которая требует выполнения кода во время выполнения, чтобы быть инициализированным. Это включает в себя все, что требует распределений кучи, таких как векторы или хеш-карты, а также все, что требует вычислений неконфекционных функций.

-Lazy_static Crate

Использование простое: мы завершаемstaticДекларация на макросе.

lazy_static! {
    static ref REGEXP_WAREHOUSE_ENDPOINT: Regex = Regex::new(r"^WAREHOUSE__(?<index>\d)__ENDPOINT.*").unwrap();
}

Мы достигли того, что хотели. Тем не менее, мы можем добиться большего.

LazyLockза победу

Ржавчина 1.80 добавляетLazyLockПолемLazyLockявляется встроенной точной заменой дляlazy_staticмакро.

https://x.com/13erbse/status/1816491350235173228?embedable=true

ДокументацияLazyLockпросто:

pub struct LazyLock<T, F = fn() -> T> { /* private fields */ }

Значение, которое инициализируется на первом доступе.

Этот тип представляет собой безопасную нить Lazycell, и он может использоваться в статике. Поскольку инициализация может быть вызвана из нескольких потоков, любой вызов из деревьев заблокирует вызову, если в настоящее время будет запущена другая подпрограмма инициализации.

-Лазилок

На этом этапе мы можем использовать его напрямую:

static REGEXP_WAREHOUSE_ENDPOINT: LazyLock<Regex> =
        LazyLock::new(|| Regex::new(r"^WAREHOUSE__(?<index>\d)__ENDPOINT.*").unwrap());

OnceLock

В качестве альтернативы можно использоватьOnceLockот ржавчины 1.70.

pub struct OnceLock<T> { /* private fields */ }

Примитив синхронизации, который может быть номинально записан только один раз.

Этот тип-безопасная потокаOnceCell, и может использоваться в статике. Во многих простых случаях вы можете использоватьLazyLock<T, F>Вместо этого, чтобы получить преимущества этого типа с меньшими усилиями:LazyLock<T, F>"Похоже"&TПотому что он инициализируется сFна Дереф! Где сияет в том, что Lazylock слишком прост, чтобы поддержать заданный корпус, так как Lazylock не допускает дополнительных входов на свою функцию после вызова после вызоваLazyLock::new(|| ...)Полем

-Наступил

Использование совершенно другое:

static REGEXP_WAREHOUSE_ENDPOINT: OnceLock<Regex> = OnceLock::new();       //1

let endpoint = REGEXP_WAREHOUSE_ENDPOINT.get_or_init(
        || Regex::new(r"^WAREHOUSE__(?P<index>\d+)__ENDPOINT$").unwrap()); //2

endpoint.find("whatever").is_some()                                        //3
  1. СоздатьOnceLock
  2. Получить или инициализировать переменную
  3. Используйте переменную

Краткое содержание

В этом посте мы описали несколько вариантов для создания ленивых инициализированных переменных. Раньше нам приходилось полагаться наlazy_staticящик. С Rust 1.80 мы можем заменить его наLazyLockПолем Если вам нужен дополнительный ввод послеLazyLock::new()ВOnceLockтвой друг.

Идти дальше:

  • Ключевое слово const
  • Lazy_static Crate
  • Структура Lazylock
  • Структура

Первоначально опубликовано вJava Geek1 июня 2025 года


Оригинал
PREVIOUS ARTICLE
NEXT ARTICLE