Взгляните на эту замечательную функцию, появившуюся в новой версии Rust

Вчера вышла новая версия Rust, и в ней есть несколько дополнений, которые будут действительно полезны для многих проектов. Кратко остановимся на семье Once.

OnceCell и OnceLock

Новый ящик сообщества был создан на всем пути от списка зависимостей до включения в состав стабильной библиотеки std. Это происходит не в первый раз, но все же это выдающийся подвиг, поскольку это признание требует соблюдения многих соглашений и характеристик. Я говорю о once_cell, полезном ящике с более чем 129 миллионами загрузок. Давайте посмотрим на примере, почему это хорошее дополнение к стандартной библиотеке.

«const»: непостоянный

Константы — один из столпов программирования; они обеспечивают стабильность между компонентами, использующими одно и то же значение, и в то же время сокращают инициализацию и выделение памяти, поскольку будет существовать только один экземпляр элемента. Но не все может быть постоянным. По крайней мере, не в Rust.

Приведенный выше код пытается определить список действительных адресов, которые могут быть общими для многих компонентов, как мы обычно делаем, когда определяем SERVER_ADDRESS запускаемые веб-службы. Этот постоянный список гарантирует нам, что если какой-либо из этих адресов необходимо изменить, нам нужно изменить только одну строку кода, и все компоненты, использующие их, будут продолжать работать, но это не компилируется, как вы можете видеть ниже:

error[E0015]: cannot call non-const fn `<Vec<&str> as From<[&str; 3]>>::from` in constants
 --> oncelock/src/main.rs:3:30
  |
3 |   const ADDRESSES: Vec<&str> = Vec::from([
  |  ______________________________^
4 | |     "http://validaddress.com",
5 | |     "http://mainmirror.com",
6 | |     "http://134.67.23.1:8090"
7 | | ]);
  | |__^

Ошибка проста: Vec::from это non-const, флаг Rust, идентифицирующий функции, которые нельзя использовать в области const. Почему? Потому что константы разрешаются во время компиляции. Это означает, что, например, const PORT: i32 = 8080 не существует во время выполнения. Rust просто заменит каждое вхождение PORT своим значением. Это также означает, что куча недоступна для констант.

Мы не можем создать этот вектор, потому что все три адреса будут выделены в куче, если мы используем Vec. Но обходной путь пришел, как видите:

Используя новый OnceLock, мы можем определить ADDRESSES, который может быть инициализирован только один раз, не может быть переопределен, глобально доступен и будет разрешаться в одно и то же значение везде, где он использовался. Звучит знакомо, верно? Именно эти характеристики делают константы ключевым понятием в программировании. Действительно, у него нет такой оптимизации компилятора, как у констант, но достаточно близко.

OnceLock — это потокобезопасная и статическая версия OnceCell, реальная основа этого ящика, поэтому не забудьте проверить ее. Взгляните также на LazyCell и LazyLock. Они еще не стабильны, но взяты из одного ящика и построены по той же концепции, так что это тоже будут действительно хорошие инструменты.

И более

Стабилизация этих функций — самое большое изменение, но не единственное. Я хочу подчеркнуть, что протокол разреженного груза теперь используется по умолчанию. Это приведет к значительному увеличению скорости запросов индекса crates.io. Да, вам следует обновить все ваши файлы Dockerfile до новой версии, чтобы время, затрачиваемое на чтение crates.io при создании нового образа Rust, значительно сократилось, а это означает, что ваши конвейеры CI/CD будут работать гораздо быстрее.



Проверьте все объявление и не забудьте увидеть все новые стабилизированные API, так как они также привносят много хороших вещей, таких как Result::is_err_and, который мы использовали в этом же посте.

Как всегда, примеры можно найти на GitHub. До встречи в следующей статье!