Rust 教程 目录

Rust 的基本语法

变量和常量

变量声明

在 Rust 中,变量默认是不可变的。这意味着一旦一个变量被赋予了一个值,它就不能再被改变。你可以使用 let 关键字来声明一个变量:

如果你想声明一个可变变量,你需要在 let 关键字后面加上 mut 关键字:

常量声明

常量是不可变的,并且必须在声明时初始化。常量可以使用任何类型,但它们的类型必须能被推断出来或者明确指定。常量通常用于表示不会改变的值。声明常量需要使用 const 关键字:

类型注解

虽然 Rust 有自动类型推断的能力,但在某些情况下,你可能需要显式地指定变量的类型。这可以通过类型注解来实现。例如:

在这个例子中,guess 被明确地指定为 u32 类型。

数据类型

基本数据类型

Rust 提供了多种基本数据类型,包括整型、浮点型、布尔型和字符型。

整型

Rust 提供了多种有符号和无符号的整型,每种都有不同的位数。常见的有 i8, i16, i32, i64, i128 以及 u8, u16, u32, u64, u128。例如:

浮点型

Rust 有两种浮点类型:f32f64。其中 f64 是默认类型。例如:

布尔型

布尔类型只有两种取值:truefalse。例如:

字符型

Rust 使用 char 类型来表示单个 Unicode 字符。字符必须用单引号包围。例如:

复合类型

元组

元组是一种将多个不同类型的数据组合在一起的方式。元组中的元素可以是任意类型,但它们的类型和数量在定义时必须确定。例如:

数组

数组是一系列相同类型的值。数组的长度在编译时确定,不能改变。例如:

函数

函数定义

函数在 Rust 中通过 fn 关键字定义。函数可以接受参数,并且可以返回一个值。例如:

在这个例子中,add_one 函数接受一个 i32 类型的参数并返回一个 i32 类型的值。

参数和返回值

函数可以接受任意数量的参数,每个参数都需要指明类型。同样,函数也可以返回任意类型的值,返回类型也需要在函数签名中声明。例如:

控制流

Rust 支持多种控制流语句,如 ifelseloopwhilefor 循环等。

if 语句

if 语句允许根据条件执行代码块。例如:

-- -------------------- ---- -------
--- ------ - --

-- ------ - - -- - -
    ---------------- -- --------- -- ----
- ---- -- ------ - - -- - -
    ---------------- -- --------- -- ----
- ---- -- ------ - - -- - -
    ---------------- -- --------- -- ----
- ---- -
    ---------------- -- --- --------- -- -- -- -- ----
-

while 循环

while 循环允许重复执行一段代码直到条件不再满足。例如:

for 循环

for 循环提供了一种遍历集合(如数组或向量)的方法。例如:

结构体和枚举

结构体

结构体是一种用户自定义的数据类型,允许你将一组相关的字段组合在一起。例如:

-- -------------------- ---- -------
------ ---- -
    --------- -------
    ------ -------
    -------------- ----
    ------- -----
-

-- ----------------- ------- --------- ------- -- ---- -
    ---- -
        ------
        ---------
        ------- -----
        -------------- --
    -
-

--- ----- - ----------------------------------------------- ---------------------------------

枚举

枚举允许你定义一个类型由一组可能的值组成。例如:

-- -------------------- ---- -------
---- ------- -
    -----
    ---- - -- ---- -- --- --
    --------------
    ---------------- ---- -----
-

---- ------- -
    -- ----------- -
        -- -------
    -
-

--- - - --------------------------------------
---------

模块系统

Rust 使用模块系统来组织代码。模块帮助你管理命名空间,并且可以用来封装代码。例如:

-- -------------------- ---- -------
--- -------------- -
    --- --- ------- -
        --- -- ----------------- --
    -
-

--- --- -------------------------------

-- ------------- --

--- ------------- -
    --- ------ --------- -
        --- ------ -------
        --------------- -------
    -

    ---- --------- -
        --- -- ------------- ----- -- --------- -
            --------- -
                ------ --------------------
                --------------- ------------------------
            -
        -
    -

    --- ---- --------- -
        -----
        ------
    -
-

-- ------------------- -
    ---------------------------

    --- --- ---- - ----------------------------------------
    ---------- - ----------------------
    ------------- ---- -- ----- -------- ------------

    --- ------ - -------------------------------
    --- ------ - --------------------------------
-

在这个例子中,front_of_houseback_of_house 都是模块,hostingfront_of_house 的子模块。eat_at_restaurant 函数展示了如何使用这些模块中的类型和函数。

错误处理

Result 类型

Rust 使用 Result 类型来处理错误。Result 是一个枚举,有两种可能的状态:OkErr。例如:

-- -------------------- ---- -------
--- --------------

-- ------------------------- -- -------------- --------------- -
    --- - - ------------------------

    --- --- - - ----- - -
        -------- -- -----
        ------ -- ------ -------
    --

    --- --- - - --------------

    ----- --------------------- -- -
        ----- -- ------
        ------ -- -------
    -
-

-- -------- --- ---
-- ------------------------------- -- -------------- --------------- -
    --- --- - - -------------------------
    --- --- - - --------------
    --------------------- ----
    -----
-

在这个例子中,read_username_from_file 函数展示了如何使用 match 来处理 Result 类型的返回值。而 read_username_from_file_short 函数则使用了更简洁的 ? 操作符来处理错误。

泛型

泛型函数

泛型允许你在不指定具体类型的情况下编写代码。这样可以使你的代码更加通用和复用性更高。例如:

-- -------------------- ---- -------
-- ---------- ---------- - ----------- ----- -- - -
    --- --- ------- - --------

    --- ----- -- ----------- -
        -- ---- - ------- -
            ------- - -----
        -
    -

    -------
-

-- ------ -
    --- ----------- - -------- --- --- ---- ----

    --- ------ - ----------------------
    ------------- ------- ------ -- ---- --------

    --- --------- - --------- ---- ---- -----

    --- ------ - --------------------
    ------------- ------- ---- -- ---- --------
-

在这个例子中,largest 函数接受一个泛型参数 T,并且要求 T 实现 PartialOrdCopy 特征。这意味着这个函数可以用来找出任何实现了这些特征的类型的最大值。

泛型结构体

你也可以为结构体定义泛型。例如:

-- -------------------- ---- -------
------ -------- -
    -- --
    -- --
-

------- -------- -
    -- -------- -- -- -
        -------
    -
-

---- ---------- -
    -- --------------------------- -- --- -
        --------------- - ----------------------
    -
-

-- ------ -
    --- - - ----- - -- -- -- -- --
    ------------- - ---- -------

    --- -- - ----- - -- ---- -- --- --
    ------------------ ---- ------- ---- ---------------------------
-

在这个例子中,Point 结构体是一个泛型结构体,可以存储任意类型的 xy 坐标。对于特定的 f32 类型,我们还为其定义了一个方法 distance_from_origin,用于计算原点到该点的距离。

生命周期

生命周期注解

生命周期注解确保引用在其作用域内始终有效。这对于避免悬垂引用非常重要。例如:

-- -------------------- ---- -------
-- -------------- --- ---- -- --- ---- -- --- --- -
    -- ------- - ------- -
        -
    - ---- -
        -
    -
-

-- ------ -
    --- ------- - ------------------ ------ -- -------
    -
        --- ------- - --------------------
        --- ------ - ------------------------- ------------------
        ------------- ------- ------ -- ---- --------
    -
-

在这个例子中,longest 函数接受两个字符串切片引用作为参数,并返回一个引用。生命周期注解 'a 确保返回的引用与输入的引用具有相同的生命周期。

生命周期省略规则

Rust 编译器会尝试应用一些生命周期省略规则,以减少显式生命周期注解的需求。例如:

-- -------------------- ---- -------
-- ------------- ----- -- ---- -
    --- ----- - -------------

    --- --- ------ -- ------------------------ -
        -- ---- -- -- - -
            ------ ---------
        -
    -

    ------
-

-- ------ -
    --- --------- - ------------------- --------

    -- ---------- ----- -- ------ -- ---------
    --- ---- - ---------------------------

    ------------- ----- ---- --- ---- ------
-

在这个例子中,first_word 函数接受一个字符串切片引用,并返回一个字符串切片引用。由于 &str 类型的生命周期是隐式的,所以不需要显式地添加生命周期注解。

Trait

定义 Trait

Trait 是一种定义共享行为的方式。它们类似于 Java 中的接口。例如:

-- -------------------- ---- -------
----- ------- -
    -- ---------------- -- -------
-

------ ----------- -
    --------- -------
    --------- -------
    ------- -------
    -------- -------
-

---- ------- --- ----------- -
    -- ---------------- -- ------ -
        ------------ -- -- ------ -------------- ------------ --------------
    -
-

------ ----- -
    --------- -------
    -------- -------
    ------ -----
    -------- -----
-

---- ------- --- ----- -
    -- ---------------- -- ------ -
        ------------ ---- -------------- -------------
    -
-

-- ------ -
    --- ------- - ----------- -
        --------- ---------------------- --- --- ------- --- ----------------
        --------- ------------------------- --- ------
        ------- -------------------------
        -------- ---------------------- --------- --- --------- ---------- -------- --- ---- ---- ------- ------- --- -----------
    --

    ------------- ------- ---------- ---- ---------------------

    --- ----- - ----- -
        --------- -----------------------------
        -------- ---------------- ------- -- --- -------- ------- ----- ---------
        ------ ------
        -------- ------
    --

    ----------- --- ------ ---- -------------------
-

在这个例子中,Summary Trait 定义了一个 summarize 方法。然后,我们为 NewsArticleTweet 类型实现了这个 Trait。

组合 Trait

你可以通过在 Trait 中包含其他 Trait 来组合它们。例如:

-- -------------------- ---- -------
--- ------------------

----- ------------- ------- -
    -- -------------------- -
        --- ------ - -----------------
        --- --- - -------------
        -------------- -------------- - ----
        ---------------- - ------------ - ----
        ----------- -- --- --------
        ---------------- - ------------ - ----
        -------------- -------------- - ----
    -
-

------ ----- -
    -- ----
    -- ----
-

---- ------- --- ----- -
    -- ---------- -- ---- ------------------------ -- ---------------- -
        --------- ----- ----- ------- -------
    -
-

---- ------------ --- ----- --

-- ------ -
    --- - - ----- - -- --- -- -- --
    ------------------
-

在这个例子中,OutlinePrint Trait 包含了 Display Trait。因此,任何实现了 OutlinePrint Trait 的类型也必须实现 Display Trait。通过这种方式,你可以将多个相关的行为组合在一起,使代码更加模块化和易于理解。

以上就是 Rust 的基本语法概述。希望这些示例和解释能帮助你更好地理解和掌握 Rust 的核心概念。

纠错
反馈