Введение#
Константы const
— один из базовых инструментов в Rust который как и переменные позволяет сохранять какие-либо данные в памяти. На первый взгляд они могут показаться похожими на переменные. Но есть несколько ключевых отличий, которые делают их полезными в определённых ситуациях. Давайте разберёмся, как их использовать, зачем они нужны и какие подводные камни могут нам встретиться.
Отличие констант от переменных#
Начнём с главного: константы неизменяемы. В отличие от let
, которое хоть и может создавать неизменяемые переменные let x = 5
но их всегда можно перезаписать через затенение let x = 6
С константами такой трюк не пройдёт: значение констант фиксировано в момент компиляции и не может быть изменено.
Два важных момента:
- Область видимости
- Обычные переменные живут только внутри своего блока
{}
скоупа - Константы можно объявлять на уровне файла. Они будут доступны на протяжении всего кода в файле
- Обычные переменные живут только внутри своего блока
- Когда вычисляется значение
- Переменные могут “принимать” значения во время выполнения
let user_input = read_line()
- Константы должны быть известны при компиляции - нельзя присвоить им результат вычислений в рантайме
- Переменные могут “принимать” значения во время выполнения
Как объявить константу?#
Синтаксис прост:
const ИМЯ_КОНСТАНТЫ: Тип = значение;
Пример:
const MAX_CONNECTIONS: u32 = 100;
🔥 Важные правила:
- Старайтесь придерживаться именования
SCREAMING_SNAKE_CASE
-> заглавные буквы и подчёркивание:
- Так принято в Rust и во многих других языках
- Это помогает сразу понять, что перед вами константа
- Нельзя изменять значение константы:
MAX_CONNECTIONS = 200
-> получим ошибку компиляции! - Нельзя затенять:
const FAST_LANG: &str = "Rust";
fn main(){
println("The {FAST_LANG} language");
let FAST_LANG = "Dart"; // Ошибка! Константы нельзя переопределять
}
- Нужно обязательно указать тип после двоеточия
Зачем же так строго? Компилятор Rust следует принципу “явное лучше неявного”. Если бы константы можно было затенять - код становился бы менее предсказуемым и проще было бы допустить ошибку.
Где используют константы?#
Знаменитые “магические числа”#
Вместо:
if users.len() > 100 { ... }
Лучше написать:
const MAX_USERS: usize = 100;
if users.len() > MAX_USERS { ... }
Глобальные настройки#
Например, лимиты или таймауты, коды ошибок:
const REQUEST_TIMEOUT: u64 = 5000; // 5 секунд
Константные вычисления#
Rust позволяет делать простые вычисления в const:
const SECONDS_IN_HOUR: u64 = 60 * 60; // Компилятор вычислит это заранее
⚠️ Что нельзя делать с константами#
- Нельзя брать значение из рантайма например из пользовательского ввода
let user_input = get_user_input();
const INPUT: &str = user_input; // Ошибка!
Для таких случаев лучше использовать обычные переменные.
- Нельзя изменять элементы внутри массива/коллекции
Если массив или коллекция объявлены как const их содержимое неизменяемо:
const NUMBERS: [i32; 3] = [1, 2, 3];
NUMBERS[0] = 5; // Ошибка!
Итоги#
Константы в Rust отлично подходят:
- Для неизменяемых значений известных заранее
- Для замены “магических чисел” в коде
- Для глобальных параметров которые не меняются
Не забывайте что:
- Нельзя изменять или затенять константы
- Значение должно вычисляться на этапе компиляции
SCREAMING_SNAKE_CASE
- правило наименования для констант
На последок совет: если не можете придумать название константы, подумайте к какой предметной области относится ее значение, а также читайте чужой код. Лучше если это будут исходники больших документированных проектов. Так вы получите насмотренность и зафиксируете для себя правильные наименования.