Rust Tutorial: Learn Rust from scratch
Best free online courses

Rust Tutorial: Learn Rust from scratch

Rust Tutorial: Learn Rust from scratch

Учебное пособие по Rust: изучение Rust с нуля


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

Фактически, в 2020 году Ржавчина был признан самым любимым языком программирования в опросе разработчиков Stack Overflow пятый год подряд. Многие разработчики настаивают на том, что Rust вскоре обгонит C и C++ из-за проверки Rust на заимствование и решения таких давних проблем, как управление памятью и неявный vs. explicit typing.

Сегодня мы поможем вам начать работать с ржавчиной независимо от вашего уровня опыта. Мы изучим, что отличает Rust от других языков, выучим его основные компоненты и поможем вам написать свою первую программу Rust!

Что такое Ржавчина? (What is Rust?)

Rust - это многопарадигмальный, статически-типизированный язык программирования с открытым исходным кодом, используемый для построения операционных систем, компиляторов и других аппаратных и программных средств. Он был разработан Грейдоном Хоаром (Graydon Hoare) в компании Mozilla Research в 2010 году.

Ржавчина оптимизирована с точки зрения производительности и безопасности, особенно с точки зрения приоритета безопасного параллелизма. Язык больше всего похож на C или C++, но использует проверку заемщика для подтверждения безопасности ссылок.

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

Зачем тебе учить Раста? (Why should you learn Rust?)

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

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

Здравствуйте, мир в ржавчине (Hello World in Rust)

Лучший способ понять Ржавчину - это получить практические навыки. Мы расскажем, как написать твою первую программу "Привет-мир" в "Расте".

fn main() {
    println!("Hello World!");
}

Давайте разобьем куски этого кода. (Let’s break down the pieces of this code.)

функция (fn) (function - fn)

Сокращение fn означает "функция" function. In Rust (и большинстве других языков программирования) функция означает "скажи мне какую-нибудь информацию, я что-нибудь сделаю, а потом дам тебе ответ".

главный сайт (main)

Главная функция - это то, с чего начинается ваша программа.

parentheses ()

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

curly braces or brackets { }

Они называются фигурными скобками или скобками. Они определяют начало и конец нашего тела кода. Тело скажет, что делает главная функция.

чертёнок! (println!)

Это макрос, который очень похож на функции. Он означает "распечатать и добавить новую строку". Пока можно думать о печати как о функции. Разница в том, что она заканчивается восклицательным знаком (!).

("Привет, мир!") ("Hello, world!")

Это список параметров для макро-вызова. Мы говорим: "Назовите этот макрос, называемый println с этими параметрами". Это то же самое, что основная функция имеет список параметров, за исключением того, что у макроса println есть параметр. Подробнее о функциях и параметрах мы рассмотрим позже.

"Привет, мир!" ("Hello, world!")

Это строка. Строки - это связка букв (или символов), собранных вместе. Мы помещаем их внутри двойных кавычек ("), чтобы пометить как строки. Затем мы можем передать их для макросов, таких как println! и других функций, с которыми мы поиграем позже.

semicolon ;

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

Основы синтаксиса ржавчины (Rust Syntax Basics)

Теперь давайте рассмотрим некоторые фундаментальные части программы Rust и то, как их реализовать.

Переменные и подвижность (Variables and Mutability)

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

(let [variable_name] = [value];)

Имя переменной должно быть чем-то описательным, описывающим, что означает значение. Например:

(let my_name = "Santosh";)

Здесь мы создали переменную под названием my_name и установили ее значение `'Santosh''.

Совет: (Note) - Всегда называйте переменные строчной буквой в начале и заглавными буквами для обозначения начала нового слова.В Rust переменные по умолчанию неизменяемы, что означает, что их значение не может быть изменено после установки.

Например, этот код выдаст ошибку при компиляции: (For example, this code will give an error during compilation:)

fn main() {
    let x = 5;
    println!("The value of x is: {}", x);
    x = 6;
    println!("The value of x is: {}", x);
}

Ошибка из четвертой строки, где мы пытаемся установить x = 6. Так как мы уже установили значение x во второй строке, мы не можем изменить это значение.

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

Представьте себе, что у нас есть functionA, которая полагается на переменную, имеющую значение 10, и functionB, которая изменяет эту же переменную. functionA будет сломана!

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

Чтобы переопределить это значение по умолчанию и создать мутируемую (изменяемую) переменную, объявите ее как:

(let mut x = 5;)

Мутируемые переменные чаще всего используются в качестве итерационных переменных или переменных внутри структур цикла.

Типы данных (Data Types)

Кнастоящему времени мы увидели, что можно задавать значения переменных как фразами (известными как строки), так и целыми числами. Эти переменные представляют собой различные типы данных, тэг, описывающий, какую форму значения он содержит и какие операции он может выполнять.

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

Вы можете выбрать явный ввод переменных с помощью команды : &[type] между именем и значением переменной.

Например, мы можем переписать декларацию my_name как: (For example, we can rewrite our my_name declaration as:)

let my_name = "Santosh"; //implicitly typed 
let my_name: & str = "Santosh"; // explicitly typed

набор позволяет гарантировать, что переменная будет набрана определенным образом и избежать ошибок, когда тип переменной может быть неоднозначным. Ржавчина сделает все возможное, но это может привести к неожиданному поведению.

Представьте себе, что у нас есть переменный ответ, который записывает ответ пользователя на форму.

(let answer = "true";)

Rust неявно напечатает эту переменную как строку, потому что она находится в кавычках. Тем не менее, мы, вероятно, имели в виду, что эта переменная является булевой, которая является двоичной опцией между true и false.Чтобы избежать путаницы от других разработчиков и гарантировать, что синтаксическая ошибка будет поймана, мы должны изменить объявление:

(let answer: bool = true;)

Основные типы ржавчины: (Rust’s basic types are:)

  • Integer: Whole numbers
  • Float: Numbers with decimal places
  • Boolean: binary true or false
  • String: collections of characters enclosed in quotation marks
  • Char: A Unicode scalar value that represents a specific character
  • Never: a type with no value, marked by !

Функции (Functions)

Функции представляют собой наборы связанных Rust-кодов, объединенных под коротким названием и вызываемых из других мест в программе.

До сих пор мы использовали только базовую функцию main(). Ржавчина также позволяет нам создавать собственные дополнительные функции, необходимые для большинства программ. Функции часто представляют собой одну повторяющуюся задачу, такую как addUser или changeUsername. Затем вы можете повторно использовать эти функции, когда захотите выполнить то же самое действие.

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

Here’s the format to declare a function:

fn [functionName]([parameterIdentifier]: [parameterType]) {
    [functionBody]
}

функция (fn)

Это говорит ржавчине, что следующий код является декларацией функции.

[имя функции] ([functionName])

Здесь мы поместим идентификатор функции. Мы будем использовать идентификатор всякий раз, когда захотим вызвать функцию.

скобки (parentheses)

Мы заполним эти скобки любыми параметрами, к которым мы хотим получить доступ у функции. В этом случае нам не нужно передавать никаких параметров, поэтому мы можем оставить это поле пустым.

[параметрИдентификатор] ([parameterIdentifier])

Здесь мы бы присвоили имя переданному значению. Это имя действует как имя переменной для ссылки на параметр в любом месте тела функции.

[параметрType] ([parameterType])

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

фигурные скобки {} ( braces{} )

Эти скобки обозначают начало и конец блока кода. Код между ними выполняется при каждом вызове идентификатора функции.

[функциональное тело] ([functionBody])

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

Now we’ll add some code, let’s remake our hello-world as a function called say_hello().

fn say_hello() {
    println!("Hello, world!");
}

Совет (Note) - Вызов функции всегда можно распознать по (). Даже если параметры отсутствуют, все равно необходимо включить пустое поле параметров, чтобы показать, что это функция.

После того, как функция выполнена, мы можем вызывать ее из других частей нашей программы. Так как программа начинается в main(), то оттуда мы будем вызывать say_hello().

Вот как будет выглядеть полная программа:

fn say_hello() {
    println!("Hello, world!");
}
fn main() {
    say_hello();
}

Комментарии (Comments)

Комментарии - это способ добавить в сообщение для других программистов, чтобы с первого взгляда понять, как устроена ваша программа. Они также полезны для описания назначения сегмента кода, чтобы вы могли быстро вспомнить, что вы пытались сделать позже. Таким образом, написание хороших комментариев может быть полезно как вам, так и другим.

Есть два способа написания комментариев в Rust. Первый - использовать две передние косынки //. Затем все до конца строки игнорируется компилятором. 

For example:

fn main() {
    // This line is entirely ignored
    println!("Hello, world!"); // This printed a message
    // All done, bye!
}

Другой способ - использовать пару /* и */. Преимущество такого вида комментариев состоит в том, что он позволяет помещать комментарии в середине строки кода и облегчает написание многострочных комментариев. Недостатком является то, что во многих распространенных случаях необходимо вводить больше символов, чем просто //.

fn main(/* hey, I can do this! */) {
    /* first comment  */
    println!("Hello, world!" /* second comment */);
    /* All done, bye!
       third comment
     */
}

Совет (Note) - Вы также можете использовать комментарии для "комментирования" тех разделов кода, которые вы не хотите выполнять, но, возможно, захотите добавить обратно позже.

Условные заявления (Conditional statements)

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

Все условные операторы имеют проверяемую переменную, целевое значение и оператор условий, такой как ==, < , или > , который определяет, как они должны соотноситься. Статус переменной по отношению к целевому значению возвращает булевое выражение: true, если переменная удовлетворяет целевому значению, и false, если нет.

Например, представьте, что мы хотим создать функцию, которая создаст учетную запись для любого пользователя, у которого еще нет учетной записи. Тогда они войдут в систему.

Это пример условного оператора if. По сути, мы говорим: "Если hasAccount ложный, мы создадим учетную запись". Независимо от того, была ли у них существующая учетная запись или нет, мы запишем пользователя в их учетную запись".

Формат оператора if: (The format of an if statement is:)

if [variable] [conditionOperator] [targetValue] {
        [code body]
    }

The big 3 conditional statements are if, if else, and while:

  • if: "If the condition is true, execute, otherwise skip."
  • if else: "If the condition is true, execute code body A, otherwise execute code body B."

fn main() {
    let is_hot = false;
    if is_hot {
        println!("It's hot!");
    } else {
        println!("It's not hot!");
    }
}

See what happens if you change the value of is_hot to true)

  • while: "Repeatedly execute code body while the condition is true and move on once the condition becomes false."

while is_raining() {
    println!("Hey, it's raining!");
}

Совет (Note) - в то время как циклы требуют, чтобы проверяемая переменная была мутируемой. Если переменная никогда не изменяется, цикл будет продолжаться бесконечно.

Intermediate Rust: Ownership and Structures

Владение (Ownership)

Собственность является главной особенностью ржавчины и отчасти причиной того, что она стала настолько популярной.

Все языки программирования должны иметь систему распределения неиспользуемой памяти. Некоторые языки, такие как Java, JavaScript или Python, имеют автоматические сборщики мусора, которые автоматически удаляют неиспользуемые ссылки Низкоуровневые языки, такие как C или C++, требуют, чтобы разработчики вручную выделяли и распределяли память всякий раз, когда это необходимо.

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

Rust выделяет себя из всех этих языков, используя систему владения, которая управляет памятью с помощью набора правил, навязываемых компилятором во время компиляции.

The rules of ownership are:

  • Each value in Rust has a variable that’s called its owner.
  • There can only be one owner at a time.
  • When the owner goes out of scope, the value will be dropped.

А пока, давайте рассмотрим, как собственность работает с функциями. Объявленные переменные выделяются во время их использования. Если они передаются в качестве параметров другой функции, то выделение перемещается или копируется другому владельцу для использования там.

fn main() {
     let x = 5; //x has ownership of 5
     function(x);
}
 fn function (number : i32)   { //number gains ownership of 5
        let s = "memory";  //scope of s begins, s is valid starting here
        // do stuff with s
    }                                  // this scope is now over, and s is no
                                       // longer valid

Ключевым моментом здесь является то, как к s и x относятся по-разному. x изначально имеет право собственности на значение 5, но должен передать право собственности на номер параметра, как только выходит из области действия функции main(). Использование в качестве параметра позволяет продолжить выделение памяти 5 за пределами исходной функции.

С другой стороны, s не используется в качестве параметра и поэтому остается выделенной только в то время, когда программа находится в функции(). По окончании работы функции() значение s больше никогда не понадобится и может быть перераспределено, чтобы освободить память.

Структуры (Structures)

Еще одним из продвинутых инструментов в Ржавчине являются структуры, называемые структурами. Это пользовательские типы данных, которые можно создавать для представления типов объектов. Когда вы создаете структуру, вы определяете выборку полей, для которых все структуры этого типа должны иметь значение.

Вы можете думать об этом как о классе, похожем на классы из таких языков, как Java и Python.

The syntax for a struct declaration is:

struct [identifier] {
    [fieldName]: [fieldType],
   [secondFieldName]: [secondFieldType],
}

  • struct tells Rust that the following declaration will define a struct data type.
  • [identifier] is the name of the data type used when passing parameters, like stringori32` to String and integer types respectively.
  • {} these curly braces mark the beginning and end of the variables required for the struct.
  • [fieldName] is where you name the first variable all instances of this struct must have. Variables within a struct are known as fields.
  • [fieldType] is where you explicitly define the data type of the variable to avoid confusion.

Например, можно сделать struct Car, который включает в себя марку строковой переменной и год целой переменной.

struct Car{
    brand: String,
    year: u16,
};

Каждый экземпляр типа Car должен предоставлять значение для этих полей по мере их создания. Мы создадим экземпляр "Автомобиль", чтобы представить индивидуальный автомобиль с ценностями как для марки, так и для года.

let my_car = Car {
    brand: String:: from ("BMW"), //explicit type to String
    year: 2009,
};

Подобно тому, как мы определяем переменные с примитивными типами, мы определяем переменную Car с идентификатором, на который потом будем ссылаться.

let [variableIdentifier] = [dataType] {
//fields
}

Оттуда мы можем использовать значение этих полей с синтаксисом [variableIdentifier]. [поле] [field]. Rust интерпретирует это утверждение как "какое значение [поле] для переменной [идентификатор]? ”.

println!(
        "My car is a {} from {}",
        my_car.brand, my_car.year
    );
}

Here’s what our struct looks like all together:

fn main () {
struct Car{
    brand: String,
    year: u16,
};

let my_car = Car {
        brand: String:: from ("BMW"),
    year: 2009,
};

println!(
        "My car is a {} from {}",
        my_car.brand, my_car.year
    );
}

В целом, структуры - это отличный способ хранить всю информацию, относящуюся к типу объекта, вместе для реализации и ссылки в рамках всей программы.

Rust Build System: Грузовой (Rust Build System: Cargo)

Cargo - это система сборки и менеджер пакетов Rust. Это необходимый инструмент для организации проектов Rust путем перечисления библиотек, необходимых для проекта (так называемых зависимостей), автоматической загрузки отсутствующих зависимостей и сборки программ Rust из исходных текстов.

Программы, с которыми мы сталкивались до сих пор, достаточно просты, чтобы не нуждаться в зависимостях. Как только вы начнете создавать более сложные программы, вам понадобится Грузовой автомобиль, чтобы получить доступ к возможностям инструментов, выходящим за рамки стандартной библиотеки. Cargo также полезен при загрузке проектов в портфолио Github, так как в них хранятся все части и зависимости.

Грузовой автомобиль автоматически устанавливается вместе с компилятором (rustc) и генератором документации (rustdoc) как часть Rust Toolchain, если Вы скачали Rust с официального сайта. Вы можете проверить, что Грузовой автомобиль установлен, введя следующую команду в командной строке:

$ cargo --version

Чтобы создать проект "Грузовой груз", запустите следующие действия в операционной системе CLI:

$ cargo new hello_cargo
$ cd hello_cargo

Первая команда создает новый каталог под названием hello_cargo. Вторая 
выбирает новый каталог.

Он генерирует манифест под названием Cargo.toml, который содержит все метаданные, необходимые Cargo для компиляции вашего пакета, и файл main.rs, отвечающий за компиляцию вашего проекта.Чтобы увидеть это, введите:

$ tree

Вы также можете перейти к местоположению Вашего каталога, чтобы открыть файл Cargo.toml. Внутри вы найдете коллекцию информации о проекте, которая выглядит так:

[package]
name = "hello_cargo"
version = "1.43.0"
authors = ["Your Name <you@example.com>"]
edition = "2020"
[dependencies]

Любые зависимости будут перечислены в категории зависимостей. 

После завершения проекта вы можете ввести команду $ cargo run для компиляции и запуска проекта.

Advanced concepts to learn next

Хотя многие из этих компонентов могут показаться маленькими, каждый из них приближает вас на один шаг к тому, чтобы стать мастером ржавчины! Ржавчина становится все более популярной с каждым годом, а это значит, что сейчас самое время получить навыки для создания низкоуровневых систем завтрашнего дня.

Чтобы помочь вам переобучиться программированию в области ржавчины, компания Educative создала The Ultimate Guide to Rust Programming (Окончательное руководство по программированию в области ржавчины). Этот курс углубляет изучение всех основ ржавчины, таких как перечисления, методы, структуры данных, черты и многое другое.

В конце концов, у вас будут навыки для реализации собственных проектов по кодированию ржавчины и вы станете на шаг ближе к знаниям, необходимым для карьерного роста. 

Need Help? Make a comment below and we'll help you out...❤

Post a Comment

Need Help? Make a comment below and we'll help you out...❤

Post a Comment (0)

Unimited
Blockchain Council

Academic Collaboration with World's best Instructors and Universities

Stanford Graduate School of Business Executive Education
Utaustin
Great Lakes
Stanford Center for Professional Development
Northwestern University
MIT IDSS
IIT Madras
IIIT Hyderabad
IIT Roorkee
JAIN (Deemed-to-be University)
Pes University
SRM Institute of Science and Technology (SRMIST)
Stanford Graduate School of Business Executive Education
Utaustin
Great Lakes
Stanford Center for Professional Development
Northwestern University
MIT IDSS
IIT Madras
IIIT Hyderabad
IIT Roorkee
JAIN (Deemed-to-be University)
Pes University
SRM Institute of Science and Technology (SRMIST)

Learning Collaborations