20天学会rust(二)rust的基础语法篇

这篇具有很好参考价值的文章主要介绍了20天学会rust(二)rust的基础语法篇。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

在第一节(20天学rust(一)和rust say hi)我们配置好了rust的环境,并且运行了一个简单的demo——practice-01,接下来我们将从示例入手,学习rust的基础语法。
首先来看下项目结构:
项目结构

practice-01
├── Cargo.lock # Cargo 依赖版本锁定文件
├── Cargo.toml # Cargo 主要设置文件
└── src
    └── main.rs # Rust 程序入口

项目的重点文件有两个:Cargo.toml文件和main.rs。我们首先来看下practice-01Cargo.toml

rust的灵魂——Cargo.toml

[package]
name = "practice-01"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
fast-str = "1.0.0"

其实这里是一个极简的文件,它用于管理项目的依赖项、编译选项和其他配置信息,我们来看下完整的:

[package]
name = "my_project"
version = "0.1.0"
edition = "2018"
 [dependencies]
crate_name = "version"
 [dev-dependencies]
dev_crate_name = "version"
 [build-dependencies]
build_crate_name = "version"
 [features]
feature_name = ["dependency_name/version"]
  • [package] :用于指定包的元数据,包括名称、版本和edition。名称是包的唯一标识符,版本遵循语义化版本规范,edition指定Rust编译器使用的版本。
  • [dependencies] :用于指定项目的依赖项。每个依赖项由crate名称和版本号组成,可以通过在 = 后面指定版本号或使用特定的版本约束来指定依赖项的版本。
  • [dev-dependencies] :用于指定只在开发环境中使用的依赖项,例如测试框架或代码检查工具。
  • [build-dependencies] :用于指定在构建过程中需要的依赖项,例如构建脚本或代码生成工具。
  • [features] :用于定义项目的特性(features),特性是一组可选的依赖项,可以通过在 = 后面列出依赖项的名称和版本号来指定。
    Cargo.toml文件还可以包含其他配置项,例如构建脚本、路径别名、工作空间设置等。这些配置项可以根据项目的需要进行自定义。
    通过编辑和配置Cargo.toml文件,可以管理Rust项目的依赖项、版本控制和构建过程。Cargo工具使用Cargo.toml文件来构建、测试和发布Rust项目,使得项目的管理变得简单和方便。
    更多信息可以参考rust官网文档:cargo/Cargo.toml

接下来再看main.rs的代码,我将逐行的解释下面代码

use std::io;

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

    loop {
        let mut input = String::new();
        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read input!");

        if input.contains("quit") {
            break;
        }
        i_say_what_u_say(input)
    }
}

fn i_say_what_u_say(str: String) {
    print!("{}", str)
}

use std::io;

这里有两个知识点:use::

use

在Rust中, use 关键字用于引入一个模块或类型的路径到当前作用域,以便在代码中可以直接使用该模块或类型的名称,而无需每次都写完整的路径。
use 关键字有两种常见的用法:

  1. 引入模块:可以使用 use 关键字来引入一个模块,以便在当前作用域中直接使用模块中的项(函数、结构体、枚举等)。引入模块的语法是 use 模块路径
    例如,如果想在代码中使用 std::io::Result ,可以使用 use 关键字引入该模块:
    use std::io::Result;
    然后就可以在代码中直接使用 Result ,而无需写完整的路径 std::io::Result
  2. 引入类型:可以使用 use 关键字来引入一个具体的类型,以便在当前作用域中直接使用该类型的名称。引入类型的语法是 use 类型路径
    例如,如果想在代码中使用 std::io::Error ,可以使用 use 关键字引入该类型:
    use std::io::Error;
    然后就可以在代码中直接使用 Error ,而无需写完整的路径 std::io::Error
    需要注意的是, use 关键字只是将指定的模块或类型的路径引入到当前作用域,并不会导入任何其他的项。如果想要导入模块中的所有项,可以使用 use 模块路径::* 的语法。

如果你有Java或者Go的经验,理解起来就很容易,它类似于import的用法。如果不用use也行,只不过在每次用到的时候都需要写全路径名。

::

在Rust中,::是一个作用域解析运算符,用于访问模块、结构体、枚举、常量、函数等定义在特定命名空间中的项。
下面是关::的一些用法和含义:

  1. 访问模块中的项:
mod my_module {
       pub fn my_function() {
           // 函数实现
       }
   }
   // 使用"::"来访问模块中的函数
   my_module::my_function();
  1. 访问结构体和枚举中的项:
struct MyStruct {
       my_field: i32,
   }
   // 使用"::"来访问结构体的字段
   let my_value = MyStruct { my_field: 42 };
   println!("{}", my_value.my_field);
    enum MyEnum {
       Variant,
   }
   // 使用"::"来访问枚举的变体
   let my_variant = MyEnum::Variant;
  1. 访问常量和函数:
const MY_CONSTANT: i32 = 42;
   // 使用"::"来访问常量
   println!("{}", MY_CONSTANT);
    fn my_function() {
       // 函数实现
   }
   // 使用"::"来访问函数
   my_function();

需要注意的是,::并不是一个特定于Rust的运算符,它在其他编程语言中也有类似的用法。它的作用是帮助标识和访问特定命名空间中的项。
提到了::,还有个运算符就不得不提:.

.

Rust中的 . 运算符用于访问结构体、枚举、模块和其他数据类型的字段、方法和关联常量。
. 运算符用法示例:

struct Person {
    name: String,
    age: u32,
}
 impl Person {
    fn new(name: &str, age: u32) -> Person {
        Person {
            name: name.to_string(),
            age,
        }
    }
     fn say_hello(&self) {
        println!("Hello, my name is {}", self.name);
    }
}
 fn main() {
    let person = Person::new("Alice", 25);
    println!("Name: {}", person.name);
    println!("Age: {}", person.age);
    person.say_hello();
}

rust的入口——main函数

fn main()
main是整个程序的入口,也是整个软件的灵魂。这个就不用多说了。

rust里的一等公民——i_say_what_u_say

fn i_say_what_u_say(str: String) {
    print!("{}", str)
}

这里我们定义了一个函数i_say_what_u_say。在Rust中,函数是一种用于封装可执行代码的基本构建块。以下是关于Rust函数的介绍:

函数定义

在Rust中,函数的定义使用 fn 关键字,后跟函数名称、参数列表和返回类型。函数体由一对花括号 {} 包围,用于包含实际的代码逻辑。

fn add(a: i32, b: i32) -> i32 {
    let sum = a + b;
    sum
}

上述代码定义了一个名为 add 的函数,它接受两个 i32 类型的参数 ab ,并返回一个 i32 类型的结果。函数体中计算了 ab 的和,并将其作为函数的返回值。

函数调用

要调用一个函数,只需使用函数名称后跟参数列表,并使用圆括号 () 包围参数。

let result = add(3, 5);
println!("Result: {}", result);

上述代码调用了之前定义的 add 函数,传递参数 35 。函数的返回值被存储在 result 变量中,并通过 println! 宏打印出来。

函数参数和返回值

Rust函数可以有多个参数,并且每个参数都需要指定类型。函数可以有一个返回值,其类型在函数定义中使用 -> 符号指定。如果函数没有返回值,可以使用 () 表示空元组类型。

fn greet(name: &str) {
    println!("Hello, {}!", name);
}

fn multiply(a: i32, b: i32) -> i32 {
    a * b
}

// 通过元组,可以包含多个返回值
fn multi_result(a:i32, b:i32) -> (i32,i32){
	(a,b)
}

上述代码展示了两个函数的例子。 greet 函数接受一个名为 name 的字符串引用参数,并没有返回值。 multiply 函数接受两个 i32 类型的参数,并返回它们的乘积。

函数作为一等公民

在Rust中,函数是一等公民,这意味着函数可以像其他值一样被传递、赋值和返回。可以将函数作为参数传递给其他函数,也可以将函数作为返回值返回。

fn add(a: i32, b: i32) -> i32 {
    a + b
}
 fn subtract(a: i32, b: i32) -> i32 {
    a - b
}
 fn operation(op: fn(i32, i32) -> i32, a: i32, b: i32) -> i32 {
    op(a, b)
}
 let result = operation(add, 3, 5);
println!("Result: {}", result);

上述代码展示了如何将函数作为参数传递给 operation 函数,并在 operation 函数内部调用传递的函数。

println!(“Hello!”);

接下来我们再看下函数体的内容。 第一行就是println!("Hello!"), 就很疑惑,要说是函数吧,为什么有个呢?要说不是函数吧,长得又太tm像了。 其实这是rust的另一个功能,

Rust 中的宏(Macro)是一种元编程工具,用于在编译时生成代码。宏允许你在编写 Rust 代码时创建自定义的代码片段,以简化重复的代码,增加代码的可读性和可维护性。宏可以接受不同数量和类型的参数,并根据这些参数生成代码。
下面是一个使用 Rust 自定义宏的例子:

macro_rules! greet {
    ($name:expr) => {
        println!("Hello, {}!", $name);
    };
}
 fn main() {
    greet!("Alice");
    greet!("Bob");
}

在上面的例子中,我们定义了一个名为 greet 的宏。这个宏接受一个表达式参数 $name ,并生成一个打印欢迎消息的代码块。
main 函数中,我们使用 greet! 宏两次,分别传入不同的参数 "Alice" "Bob"。在编译时,宏会根据我们提供的参数展开,并生成相应的代码。最终的输出将是:

Hello, Alice!
Hello, Bob!

再看println!(“Hello!”);

我们看下println!的定义

#[macro_export]
#[stable(feature = "rust1", since = "1.0.0")]
#[cfg_attr(not(test), rustc_diagnostic_item = "print_macro")]
#[allow_internal_unstable(print_internals)]
macro_rules! print {
    ($($arg:tt)*) => {{
        $crate::io::_print($crate::format_args!($($arg)*));
    }};
}

上面的代码实际上等同于

	println!("{}","Hello!");
    std::io::_print(std::format_args!("{}","Hello!"));

这样是不是就清楚多了

loop

Rust提供了几种不同的循环语句,用于重复执行代码块,loop是rust的循环实现的一种方式,

loop 循环

loop 循环是一个无限循环,它会无限次地执行一个代码块,直到遇到 break 关键字才会退出循环。

loop {
    // 无限循环的代码块
    // 可以使用 `break` 关键字来退出循环
    break;
}

loop 循环中,你可以使用 break 关键字来手动退出循环。这通常在满足某个条件时使用。

while 循环

while 循环会在满足给定条件的情况下重复执行一个代码块。

let mut i = 0;
while i < 5 {
    // 循环的代码块
    i += 1;
}

while 循环中,首先会判断条件是否为真,如果为真则执行循环体内的代码块,然后再次判断条件。如果条件为假,则退出循环。

for 循环

for 循环用于遍历一个集合或者一个范围内的元素,并执行相应的代码块。

let numbers = vec![1, 2, 3, 4, 5];
for number in numbers {
    // 循环的代码块
    println!("{}", number);
}

for 循环中,你需要提供一个可迭代的集合或者一个范围表达式。在每次循环迭代中,变量 number 会依次赋值为集合中的元素,并执行循环体内的代码块。
Rust还提供了其他一些循环相关的关键字和语法,如 continue 关键字用于跳过当前循环迭代, break 关键字用于退出循环,以及循环标签(loop label)用于在嵌套循环中指定退出的位置等。

let mut input = String::new();

这行Rust代码 let mut input = String::new(); 的含义是创建一个可变的空字符串变量 input
具体解释如下:

  • let :Rust中用于声明变量的关键字。
  • mut :表示变量是可变的(mutable),可以在后续的代码中修改其值。
  • input :变量名,可以根据需要进行命名。
  • String::new() :调用了 String 类型的 new() 函数,用于创建一个新的空字符串对象。
    这行代码的作用是创建一个可变的字符串变量 input ,并将其初始化为空字符串。这样,我们可以在后续的代码中使用 input 变量来存储用户输入或其他字符串数据。
    这里重点介绍一个点: mut

mut

mut 关键字用于声明可变变量(mutable variable)。使用 mut 关键字可以将一个变量标记为可变,允许在后续的代码中修改其值。 那么不适用mut会怎么样呢?
20天学会rust(二)rust的基础语法篇,rust,20天学会Rust,rust,开发语言,后端

error[E0596]: cannot borrow `input` as mutable, as it is not declared as mutable
 --> src/main.rs:9:24
  |
9 |             .read_line(&mut input)
  |                        ^^^^^^^^^^ cannot borrow as mutable
  |
help: consider changing this to be mutable
  |
7 |         let mut input = String::new();
  |             +++


给出了一个编译错误,并且给了修复方案,那就是在变量声明的时候加上mut, 那么是为什么呢? 这里且卖一个关子,如果有等不及的可以看我另一篇博文(rust怎么搞的,这么简单的代码也报“borrow of moved value“?)。

变量类型

这里我们定义了String类型的变量,那么rust中还有哪些常用类型呢?

  1. 整数类型(Integer Types)
    整数类型用于表示整数值。在Rust中,整数类型有多种,包括有符号整数和无符号整数,分别用 iu 前缀表示,后面跟上整数的位数。
let number: i32 = 42;
let unsigned_number: u64 = 100;
  1. 浮点数类型(Floating-Point Types)
    浮点数类型用于表示带有小数部分的数值。在Rust中,浮点数类型有两种,分别是 f32f64 ,分别表示单精度浮点数和双精度浮点数。
let float_number: f32 = 3.14;
let double_number: f64 = 3.14159265359;
  1. 布尔类型(Boolean Type)
    布尔类型用于表示真或假的值。在Rust中,布尔类型有两个可能的值,即 truefalse
let is_true: bool = true;
let is_false: bool = false;
  1. 字符类型(Character Type)
    字符类型用于表示单个Unicode字符。在Rust中,字符类型使用单引号 ' 表示。
let character: char = 'A';
  1. 数组类型(Array Type)
    数组类型用于存储固定大小的元素序列。在Rust中,数组的大小是在编译时确定的,并且所有元素的类型必须相同。
let array: [i32; 3] = [1, 2, 3];
  1. 元组类型(Tuple Type)
    元组类型用于存储多个不同类型的值。在Rust中,元组使用圆括号 () 表示。
let tuple: (i32, f64, char) = (42, 3.14, 'A');
  1. 引用类型(Reference Type)
    引用类型用于引用其他变量的值,而不是拥有自己的所有权。在Rust中,引用使用 & 符号表示。
let value: i32 = 42;
let reference: &i32 = &value;
  1. 切片类型(Slice Type)
    切片类型用于引用数组或向量的一部分数据。在Rust中,切片使用 &[T] 表示。
let array: [i32; 5] = [1, 2, 3, 4, 5];
let slice: &[i32] = &array[..3];
  1. 字符串类型(String Type)
    字符串类型用于存储文本数据。在Rust中,字符串类型由标准库提供,使用 String 表示。
let string: String = String::from("Hello, Rust!");
  1. 向量类型(Vector Type)
    向量类型用于存储可变大小的元素序列。在Rust中,向量由标准库提供,使用 Vec<T> 表示。
let mut vector: Vec<i32> = Vec::new();
vector.push(1);
vector.push(2);
vector.push(3);
  1. 函数类型(Function Type)
    函数类型用于定义函数。在Rust中,函数类型由函数的参数类型和返回类型组成。
fn add(a: i32, b: i32) -> i32 {
    a + b
}
  1. 结构体类型(Struct Type)
    结构体类型用于自定义复杂的数据结构。在Rust中,结构体使用 struct 关键字定义。
struct Person {
    name: String,
    age: u32,
}
 let person = Person {
    name: String::from("Alice"),
    age: 25,
};
  1. 枚举类型(Enum Type)
    枚举类型用于定义具有不同变体的类型。在Rust中,枚举使用 enum 关键字定义。
enum Color {
    Red,
    Green,
    Blue,
}
 let color: Color = Color::Red;

io::stdin()

        io::stdin()
            .read_line(&mut input)
            .expect("Failed to read input!");

这段代码的作用是从标准输入读取一行输入,并将其存储到一个可变的字符串变量 input 中。下面是对代码的解释:

  • io::stdin() :这是一个函数调用,返回一个标准输入的句柄(handle),用于从标准输入读取数据。
  • .read_line(&mut input) :这是对标准输入句柄调用的方法,用于读取一行输入。 &mut input 表示将输入存储到一个可变的字符串变量 input 中。 &mut 表示传递一个可变引用,以便在方法内部修改变量的值。
  • .expect("Failed to read input!"):这是一个错误处理方法。如果读取输入时发生错误,会触发一个panic,并打印出错误信息"Failed to read input!"。

if input.contains(“quit”)

        if input.contains("quit") {
            break;
        }

这段代码的作用是检查字符串变量 input 中是否包含子字符串"quit"。如果包含,则执行 break 语句,跳出当前循环。这里重点学习下if的语法

条件判断

Rust中的条件判断语法使用 ifelse 关键字来实现。下面是条件判断的语法示例和实际例子:

if condition {
    // 当条件为真时执行的代码块
} else if condition2 {
    // 当条件2为真时执行的代码块
} else {
    // 当以上条件都不满足时执行的代码块
}

示例代码:

fn main() {
    let number = 10;
     if number > 0 {
        println!("The number is positive");
    } else if number < 0 {
        println!("The number is negative");
    } else {
        println!("The number is zero");
    }
}

最后一句i_say_what_u_say(input) 再前面函数位置已经介绍过了,就不做过多介绍。至此我们学习了rust项目的基本目录结构、函数的定义、分支语法(循环、条件)和宏定义。掌握了这些基础,就能写出简单的rust程序啦。

这里留一个课后作业:写一个斐波那契函数(Leetcode)。文章来源地址https://www.toymoban.com/news/detail-631233.html

关注我,学习rust不迷路

到了这里,关于20天学会rust(二)rust的基础语法篇的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Rust 基础语法

    变量,基本类型,函数,注释和控制流,这些几乎是每种编程语言都具有的编程概念。 这些基础概念将存在于每个 Rust 程序中,及早学习它们将使你以最快的速度学习 Rust 的使用。 变量 首先必须说明,Rust 是强类型语言,但具有自动判断变量类型的能力。这很容易让人与弱

    2024年02月09日
    浏览(39)
  • Rust 基础语法学习

    rust中的程序从main函数作为入口,hello rust! 使用let定义变量: rust是强类型的,但声明是可以不写明类型,会自动推导类型。 如果要加入数据类型,也可以使用下面方式: 整数类型 按照比特位长度和有无符号分类: bit-length unsigned signed 8 u8 i8 16 u16 i16 32 u32 i32 64 u64 i

    2024年02月10日
    浏览(34)
  • 【Rust】003-基础语法:流程控制

    控制流是编程语言的一个重要概念。程序员通过控制流可以控制哪些代码要执行。在Rust中,最常见的两种控制流结构是 if 表达式和循环。 这里的 condition 必须是 bool 类型 正如这一小节的标题所说, if 其实是一个表达式,具有返回值。 需要注意的是, if 分支和 else 分支的返

    2024年02月09日
    浏览(39)
  • 【Rust】001-基础语法:变量声明及数据类型

    “一切能用 Rust 重写的项目都将或者正在用 Rust 重写” Rust 入门与实践:https://juejin.cn/book/7269676791348854839?utm_source=course_list 代码演示 执行结果 依赖 Cargo.toxml 代码 执行命令 根目录执行 整型标量类型 只要记得最低从 8 开始,到 128 结束(当然,正常情况下我们最多用到 64,

    2024年02月10日
    浏览(48)
  • 【ChatGPT辅助学Rust | 基础系列 | 基础语法】变量,数据类型,运算符,控制流

    本章节将详细介绍Rust的基础语法,包括变量,数据类型,运算符,以及控制流。每个部分都将提供详细的解释和代码示例,以便于理解和学习。 在编程语言中,变量是一种基本的概念,它们是用来存储数据的。在Rust中,变量的特性和其他语言有所不同。 在Rust中,变量的定

    2024年02月14日
    浏览(88)
  • 2023-05-20:go语言的slice和rust语言的Vec的扩容流程是什么?

    2023-05-20:go语言的slice和rust语言的Vec的扩容流程是什么? 答案2023-05-20: go版本是1.20.4。 扩容流程见源码见runtime/slice.go文件中的 growslice 函数。 growslice 函数的大致过程如下: 1.如果元素类型的大小为零,则返回具有 nil 指针但非零长度的切片。否则,下一步。 2.计算新切片的

    2024年02月05日
    浏览(45)
  • 【Rust 基础篇】Rust FFI:连接Rust与其他编程语言的桥梁

    Rust是一种以安全性和高效性著称的系统级编程语言,具有出色的性能和内存安全特性。然而,在现实世界中,我们很少有项目是完全用一种编程语言编写的。通常,我们需要在项目中使用多种编程语言,特别是在与现有代码库或底层系统交互时。为了实现跨语言的互操作性,

    2024年02月15日
    浏览(55)
  • Rust语言从入门到入坑——(2)Rust在windows上搭建开发环境

    开始搭建一个适合在windows上运行的Rust环境。 Rust支持的程序语言很多:可详见官网介绍 本文章主要是在windowns下搭建开发环境 首先,需要安装最新版的 Rust 编译工具和 Visual Studio Code。 Rust 编译工具:https://www.rust-lang.org/zh-CN/tools/install Visual Studio Code:https://code.visualstudio.com

    2024年02月09日
    浏览(52)
  • Rust软件外包开发语言的特点

    Rust 是一种系统级编程语言,强调性能、安全性和并发性的编程语言,适用于广泛的应用领域,特别是那些需要高度可靠性和高性能的场景。下面和大家分享 Rust 语言的一些主要特点以及适用的场合,希望对大家有所帮助。北京木奇移动技术有限公司,专业的软件外包开发公

    2024年02月12日
    浏览(51)
  • 【跟小嘉学 Rust 编程】三十三、Rust的Web开发框架之一: Actix-Web的基础

    【跟小嘉学 Rust 编程】一、Rust 编程基础 【跟小嘉学 Rust 编程】二、Rust 包管理工具使用 【跟小嘉学 Rust 编程】三、Rust 的基本程序概念 【跟小嘉学 Rust 编程】四、理解 Rust 的所有权概念 【跟小嘉学 Rust 编程】五、使用结构体关联结构化数据 【跟小嘉学 Rust 编程】六、枚举

    2024年02月04日
    浏览(52)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包