您现在的位置是:网站首页> PY&Rust

Rust学习资料

  • PY&Rust
  • 2024-09-30
  • 602人已阅读
摘要

Rust学习资料

Rust下载安装

Cargo创建项目编译项目等使用说明

在线Rust学习文本资料

Rust的包、模块、结构体和特征(接口)的概念

Rust学习笔记

  Rust中的关键字

  结构体方法

  结构体关联函数

  Rust 中的mod 使用

最新最全Rust编程语言入门教程

Rust编程语言入门教程

2022年末 Rust权威编程语言入门教程

Rust UI库


Rust下载安装

1. 安装Rust环境

点击进入Rust下载页面

在线体验rust编程

点击查看原文

点击查看windows下rust文档

***可在在windows的环境变量里面设置RUSTUP_HOME 以及 CARGO_HOME 通过设置这两个环境变量来设置默认安装路径。

环境变量:

变量名 值

CARGO_HOME  cargo 的安装路径(必须为绝对路径),例如D:\Rust\Cargo

RUSTUP_HOME rustup 的安装路径(必须为绝对路径),例如 D:\Rust\Rustup

RUSTUP_DIST_SERVER  https://mirrors.ustc.edu.cn/rust-static

RUSTUP_UPDATE_ROOT https://mirrors.ustc.edu.cn/rust-static/rustup

RUST_BACKTRACE full

RUST  某toolchain的目录,如%RUSTUP_HOME%\toolchains\stable-x86_64-pc-windows-gnu。

RUST_SRC_PATH  rust的源码目录,如%RUST%\lib\rustlib\src\rust\src,若你的rustlib中没有src,请执行> rustup component add rust-src。

RUSTBINPATH  %CARGO_PATH%\bin。


卸载 Rust

在任何时候如果您想卸载 Rust,您可以运行 rustup self uninstall。但我们会想念您的!

打开rustup-init.exe文件,若出现以下提示,按"Y"、回车

1.png

随后出现以下选项

1.png

如已经安装了vs2022直接选1就可以不用2手动安装

依次输入"2"、回车、"x86_64-pc-windows-gnu"、回车、"nightly"、回车、"y"、回车,随后选项更新为

2.png


随后输入"1"、回车即可开始安装最新版,等待一定时间后提示如下即表示Rust已经正常安装。

3.png


截至目前,你已安装了工具链管理工具rustup、项目构建工具cargo、Rust编译环境、Rust标准库文档

2. 配置开发工具

rustup component add rust-src rustc-dev llvm-tools-preview

1. 执行命令"cargo install racer"

2. 执行命令"cargo install rustfmt"

3. 执行命令"rustup component add rls"

4. 执行命令"rustup component add rust-analysis"

5. 执行命令"rustup component add rust-src"

6. 设置名为"RUST_SRC_HOME"的环境变量为"C:\Users\[home_dir_name]\.multirust\toolchains\nightly-x86_64-pc-windows-gnu\lib\rustlib\src\rust\src"

其中"home_dir_name"为你的家目录的目录名

7. 安装VScode编辑器

8. 安装名为rust-analyzer 的插件并重新加载后用VScode打开任意扩展名为rs的文件

9. 跟随插件引导完成配置,共有四项需要配置,其中两项用于选择rustup的工具链,由于之前的内容中只安装了nightly版本的工具链,故均只可选择nightly;另外两项一个是选择补全所用工具,选择rls即可,随后要求选择是否使用Rustfmt,选择使用即可

所有选项均可在用户设置中找到。

1.png

截至目前,理论上开发环境已经完成,且为模拟新手第一次安装的情况,我先卸载了rust并清除了相关配置后重新安装、配置了一遍,但由于可能因遗漏而未清除的配置,我的起步环境可能与你的不同,欢迎指正。

在终端中输入命令

cargo new greeting 

当前文件下下会构建一个名叫 greeting 的 Rust 工程目录


调试需要安装插件Native Debug和C/C++扩展

调试文件launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "(Windows)启动",
            "type": "cppvsdbg",
            "request": "launch",
            "program": "${workspaceFolder}/target/debug/greeting.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false
        },
        {
            "name": "(gdb)启动",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/target/debug/${workspaceFolderBasename}.exe",
            "args": [],
            "stopAtEntry": false,
            "cwd": "${workspaceFolder}",
            "environment": [],
            "externalConsole": false,
            "MIMode": "gdb",
            "miDebuggerPath": "这里填GDB所在的目录",
            "setupCommands": [
                {
                    "description": "为gdb启用整齐打印",
                    "text": "-enable-pretty-printing",
                    "ignoreFailures": true
                }
            ]
        }
    ]
}

重要目录

c:\Users\[用户名]\.cargo

c:\Users\[用户名]\.rustup

调试过程中,当要跟踪到rust内部代码时,会跳出如下提示框,这时需要建一个C:\rustc\b8cedc00407a4c56a3bda1ed605c6fc166655447的目录,并将用户目录下的.rustup\toolchains\stable-x86_64-pc-windows-msvc\lib\rustlib\src\rust\src拷到前面的目录下。这样就能跟踪到内部代码了。

1.png



Cargo创建项目编译项目等使用说明

在 Rust 中,可以使用 Cargo 工具来编译生成可执行文件。Cargo 是 Rust 的构建系统和包管理器,它简化了 Rust 项目的构建、测试和部署过程。

要使用 Cargo 编译生成可执行文件,可以按照以下步骤进行:


确保已经安装了 Rust 和 Cargo。可以从 Rust 官方网站(https://www.rust-lang.org/)下载并安装。

打开终端或命令行界面,导航到你的 Rust 项目目录。


如果你还没有创建 Rust 项目,可以使用以下命令创建一个新的二进制项目:

cargo new my_project

这将创建一个名为 "my_project" 的新目录,其中包含 Cargo.toml 配置文件和 src 目录。

进入项目目录:

cd my_project

编写你的 Rust 代码,并将其保存在 src 目录下的 main.rs 文件中。

使用以下命令编译项目:

cargo build --release

这将在项目目录下的 target/release 目录中生成优化后的可执行文件。


运行生成的可执行文件:

在 Linux/macOS 上:

./target/release/my_project


在 Windows 上:

.\target\release\my_project.exe

注意:将 "my_project" 替换为你实际的项目名称。

Cargo 还提供了其他有用的命令:

cargo run:编译并运行项目,适合开发和测试阶段。

cargo test:运行项目的单元测试。

cargo doc:生成项目的文档。

cargo clean:清理项目的构建结果。

使用 Cargo 可以大大简化 Rust 项目的管理和构建过程。它会自动处理依赖项的下载和编译,并提供了一致的项目结构和构建命令。



Rust的包、模块、结构体和特征(接口)的概念

包(Crate)和模块(Module)的区别:

包(Crate):

包是Rust中最高级别的代码组织单位。

一个包可以包含多个模块

包可以是二进制包(可执行程序)或库包(供其他程序使用的代码库)。

每个包都有一个Cargo.toml文件,用于描述包的元数据和依赖关系。


模块(Module):

模块是在包内组织代码的方式。

模块可以包含函数、结构体、特征、常量等。

模块可以嵌套,形成层次结构

模块用于控制项的可见性(公有或私有)。


示例:

// 这是一个名为 "my_package" 的包


// lib.rs (库包的根模块)

mod front_of_house {

    pub mod hosting {

        pub fn add_to_waitlist() {}

    }

}


pub fn eat_at_restaurant() {

    front_of_house::hosting::add_to_waitlist();

}


// 在同一个包中的另一个文件 (比如 src/back_of_house.rs)

pub struct Breakfast {

    pub toast: String,

    seasonal_fruit: String,

}


impl Breakfast {

    pub fn summer(toast: &str) -> Breakfast {

        Breakfast {

            toast: String::from(toast),

            seasonal_fruit: String::from("peaches"),

        }

    }

}


结构体(Struct)和特征(Trait):

结构体(Struct):

结构体是自定义数据类型,用于组合多个相关的值。

可以包含多个命名字段。

可以实现方法。


特征(Trait):

特征定义了一组方法签名,可以被其他类型实现。

类似于其他语言中的接口概念。

允许抽象和多态。

示例:


// 定义一个结构体

struct Rectangle {

    width: u32,

    height: u32,

}


// 为结构体实现方法

impl Rectangle {

    fn area(&self) -> u32 {

        self.width * self.height

    }

}


// 定义一个特征

trait Drawable {

    fn draw(&self);

}


// 为Rectangle实现Drawable特征

impl Drawable for Rectangle {

    fn draw(&self) {

        println!("Drawing a rectangle of {}x{}", self.width, self.height);

    }

}


// 另一个实现Drawable特征的结构体

struct Circle {

    radius: f64,

}


impl Drawable for Circle {

    fn draw(&self) {

        println!("Drawing a circle with radius {}", self.radius);

    }

}


// 使用特征作为参数

fn draw_shape(shape: &impl Drawable) {

    shape.draw();

}


fn main() {

    let rect = Rectangle { width: 30, height: 50 };

    let circ = Circle { radius: 10.0 };


    draw_shape(&rect);

    draw_shape(&circ);

    

// 调用 area 方法

    let area1 = rect .area(); 

    println!("The area of the rectangle is {} square pixels.", area1);


}

在这个例子中:

Rectangle和Circle是结构体。

Drawable是一个特征,定义了draw方法。

两个结构体都实现了Drawable特征。

draw_shape函数可以接受任何实现了Drawable特征的类型。

Rust没有传统意义上的类,但结构体和特征的组合提供了类似的功能:


结构体用于数据封装

impl块用于定义方法

特征用于定义接口和实现多态

这种设计提供了更大的灵活性和更清晰的代码组织







Rust学习笔记

Rust中的关键字

严格关键字

as - 强制类型转换,消除特定包含项的 trait 的歧义,或者对 use 和 extern crate 语句中的项重命名

async - 返回一个 Future 而不是阻塞当前线程( 2018版新增)

await - 暂停执行直到 Future 的结果就绪( 2018版新增)

break - 立刻退出循环

const - 定义常量或不变裸指针(constant raw pointer)

continue - 继续进入下一次循环迭代

crate - 链接(link)一个外部 crate 或一个代表宏定义的 crate 的宏变量

dyn - 动态分发 trait 对象

else - 作为 if 和 if let 控制流结构的 fallback

enum - 定义一个枚举

extern - 链接一个外部 crate 、函数或变量

false - 布尔字面值 false

fn - 定义一个函数或 函数指针类型 (function pointer type)

for - 遍历一个迭代器或实现一个 trait 或者指定一个更高级的生命周期

if - 基于条件表达式的结果分支

impl - 实现自有或 trait 功能

in - for - 循环语法的一部分

let - 绑定一个变量

loop - 无条件循环

match - 模式匹配

mod - 定义一个模块

move - 使闭包获取其所捕获项的所有权

mut - 表示引用、裸指针或模式绑定的可变性

pub - 表示结构体字段、impl 块或模块的公有可见性

ref - 通过引用绑定

return - 从函数中返回

Self - 定义或实现 trait 的类型的类型别名

self - 表示方法本身或当前模块

static - 表示全局变量或在整个程序执行期间保持其生命周期

struct - 定义一个结构体

super - 表示当前模块的父模块

trait - 定义一个 trait

true - 布尔字面值 true

type - 定义一个类型别名或关联类型

union - 定义一个 union 并且是 union 声明中唯一用到的关键字

use - 引入外部空间的符号

where - 表示一个约束类型的从句

while - 基于一个表达式的结果判断是否进行循环



保留关键字

以下关键字目前没有任何功能,不过由 Rust 保留以备将来使用

abstract

become

box

do

final

macro

override

priv

try

typeof

unsized

virtual

yield



弱关键字

unsafe - 表示不安全的代码、函数、trait 或实现

static




函数中途返回使用return

fn check_number(x: i32) -> bool {

    if x == 0 {

        return true;

    }

    false

}


fn main() {

    let result = check_number(0);

    println!("result: {}", result); // 输出:result: true

}




数据类型

整数型(Integer)

整数型简称整型,按照比特位长度和有无符号分为以下种类:

位长度 有符号 无符号

8-bit i8 u8

16-bit i16 u16

32-bit i32 u32

64-bit i64 u64

128-bit i128 u128

arch isize usize

isize 和 usize 两种整数类型是用来衡量数据大小的,它们的位长度取决于所运行的目标平台,如果是 32 位架构的处理器将使用 32 位位长度整型。



浮点数型(Floating-Point)

Rust 与其它语言一样支持 32 位浮点数(f32)和 64 位浮点数(f64)。默认情况下,64.0 将表示 64 位浮点数,因为现代计算机处理器对两种浮点数计算的速度几乎相同,但 64 位浮点数精度更高。

实例

fn main() {

    let x = 2.0; // f64

    let y: f32 = 3.0; // f32

}



布尔型

布尔型用 bool 表示,值只能为 true 或 false。


字符型

字符型用 char 表示。

Rust的 char 类型大小为 4 个字节



复合类型

元组是用一对 ( ) 包括的一组数据,可以包含不同种类的数据:


实例

let tup: (i32, f64, u8) = (500, 6.4, 1);

// tup.0 等于 500

// tup.1 等于 6.4

// tup.2 等于 1

let (x, y, z) = tup;

// y 等于 6.4

数组用一对 [ ] 包括的同类型数据。


实例

let a = [1, 2, 3, 4, 5];

// a 是一个长度为 5 的整型数组


let b = ["January", "February", "March"];

// b 是一个长度为 3 的字符串数组


let c: [i32; 5] = [1, 2, 3, 4, 5];

// c 是一个长度为 5 的 i32 数组


let d = [3; 5];

// 等同于 let d = [3, 3, 3, 3, 3];


let first = a[0];

let second = a[1];

// 数组访问


a[0] = 123; // 错误:数组 a 不可变

let mut a = [1, 2, 3];

a[0] = 4; // 正确



闭包的声明

闭包的语法声明:

|参数...| { 表达式 }


闭包的参数和返回值: 闭包可以有零个或多个参数,并且可以返回一个值。

let calculate = |a, b, c| a * b + c;


闭包的调用:闭包可以像函数一样被调用。

let result = calculate(1, 2, 3);


结构体定义

这是一个结构体定义:

struct Site {

    domain: String,

    name: String,

    nation: String,

    found: u32

}


构体实例

Rust 很多地方受 JavaScript 影响,在实例化结构体的时候用 JSON 对象的 key: value 语法来实现定义:

实例

let runoob = Site {

    domain: String::from("www.runoob.com"),

    name: String::from("RUNOOB"),

    nation: String::from("China"),

    found: 2013

};


如果你不了解 JSON 对象,你可以不用管它,记住格式就可以了:

结构体类名 {

    字段名 : 字段值,

    ...

}

这样的好处是不仅使程序更加直观,还不需要按照定义的顺序来输入成员的值。


如果正在实例化的结构体有字段名称和现存变量名称一样的,可以简化书写:

实例

let domain = String::from("www.runoob.com");

let name = String::from("RUNOOB");

let runoob = Site {

    domain,  // 等同于 domain : domain,

    name,    // 等同于 name : name,

    nation: String::from("China"),

    traffic: 2013

};


有这样一种情况:你想要新建一个结构体的实例,其中大部分属性需要被设置成与现存的一个结构体属性一样,仅需更改其中的一两个字段的值,可以使用结构体更新语法:

let site = Site {

    domain: String::from("www.runoob.com"),

    name: String::from("RUNOOB"),

    ..runoob

};

注意:..runoob 后面不可以有逗号。这种语法不允许一成不变的复制另一个结构体实例,意思就是说至少重新设定一个字段的值才能引用其他实例的值。



元组结构体

有一种更简单的定义和使用结构体的方式:元组结构体。

元组结构体是一种形式是元组的结构体。

与元组的区别是它有名字和固定的类型格式。它存在的意义是为了处理那些需要定义类型(经常使用)又不想太复杂的简单数据:


struct Color(u8, u8, u8);

struct Point(f64, f64);


let black = Color(0, 0, 0);

let origin = Point(0.0, 0.0);


实例

fn main() {

    struct Color(u8, u8, u8);

    struct Point(f64, f64);


    let black = Color(0, 0, 0);

    let origin = Point(0.0, 0.0);


    println!("black = ({}, {}, {})", black.0, black.1, black.2);

    println!("origin = ({}, {})", origin.0, origin.1);

}


结构体方法

方法(Method)和函数(Function)类似,只不过它是用来操作结构体实例的。

实例

struct Rectangle {

    width: u32,

    height: u32,

}

   

impl Rectangle {

    fn area(&self) -> u32 {

        self.width * self.height

    }

}


fn main() {

    let rect1 = Rectangle { width: 30, height: 50 };

    println!("rect1's area is {}", rect1.area());

}


请注意,在调用结构体方法的时候不需要填写 self ,这是出于对使用方便性的考虑。

一个多参数的例子:

实例

struct Rectangle {

    width: u32,

    height: u32,

}


impl Rectangle {

    fn area(&self) -> u32 {

        self.width * self.height

    }


    fn wider(&self, rect: &Rectangle) -> bool {

        self.width > rect.width

    }

}


fn main() {

    let rect1 = Rectangle { width: 30, height: 50 };

    let rect2 = Rectangle { width: 40, height: 20 };


    println!("{}", rect1.wider(&rect2));

}



结构体关联函数

之所以"结构体方法"不叫"结构体函数"是因为"函数"这个名字留给了这种函数:它在 impl 块中却没有 &self 参数。

这种函数不依赖实例,但是使用它需要声明是在哪个 impl 块中的。

一直使用的 String::from 函数就是一个"关联函数"。


实例

#[derive(Debug)]

struct Rectangle {

    width: u32,

    height: u32,

}


impl Rectangle {

    fn create(width: u32, height: u32) -> Rectangle {

        Rectangle { width, height }

    }

}


fn main() {

    let rect = Rectangle::create(30, 50);

    println!("{:?}", rect);

}


Rust 中的mod 使用

项目目录如下图。

2.1、mod.rs中是需要引入的模块代码。

2.2、main.rs和文件夹utils在src文件夹下。

1.png


2.3、mod.rs代码如下。

pub mod nation{

    pub mod government{

        pub fn govern()

        {

            let a=String::from("govern");

            println!("This is {}",a);

        }

    }

 

    mod congress{

        pub fn legislate() 

        {

            let a=String::from("legislate");

            println!("This is {}",a);

        }

    }

 

 

    pub mod court{

        pub fn judicial()

        {

            super::congress::legislate();

        }

    }

}

3、main.rs代码如下。

mod utils; 

fn main() {

    utils::nation::government::govern();

    utils::nation::court::judicial();

}

4、缩短模块引用路径方法如下。

mod utils;

use utils::nation::court::judicial;

use utils::nation::government::govern;

 

fn main() {

    govern();

    judicial()

}

5、运行结果如下图。

1.png


Rust 枚举类

枚举类在 Rust 中并不像其他编程语言中的概念那样简单,但依然可以十分简单的使用:

实例

#[derive(Debug)]


enum Book {

    Papery, Electronic

}


fn main() {

    let book = Book::Papery;

    println!("{:?}", book);

}


如果你现在正在开发一个图书管理系统,你需要描述两种书的不同属性(纸质书有索书号,电子书只有 URL),你可以为枚举类成员添加元组属性描述:


enum Book {

    Papery(u32),

    Electronic(String),

}


let book = Book::Papery(1001);

let ebook = Book::Electronic(String::from("url://..."));


如果你想为属性命名,可以用结构体语法:

enum Book {

    Papery { index: u32 },

    Electronic { url: String },

}

let book = Book::Papery{index: 1001};


Rust 中有三个重要的组织概念:箱、包、模块

箱(Crate)

"箱"是二进制程序文件或者库文件,存在于"包"中。

"箱"是树状结构的,它的树根是编译器开始运行时编译的源文件所编译的程序。

注意:"二进制程序文件"不一定是"二进制可执行文件",只能确定是是包含目标机器语言的文件,文件格式随编译环境的不同而不同。


包(Package)

当我们使用 Cargo 执行 new 命令创建 Rust 工程时,工程目录下会建立一个 Cargo.toml 文件。工程的实质就是一个包,包必须由一个 Cargo.toml 文件来管理,该文件描述了包的基本信息以及依赖项。

一个包最多包含一个库"箱",可以包含任意数量的二进制"箱",但是至少包含一个"箱"(不管是库还是二进制"箱")。

当使用 cargo new 命令创建完包之后,src 目录下会生成一个 main.rs 源文件,Cargo 默认这个文件为二进制箱的根,编译之后的二进制箱将与包名相同。


模块(Module)

对于一个软件工程来说,我们往往按照所使用的编程语言的组织规范来进行组织,组织模块的主要结构往往是树。Java 组织功能模块的主要单位是类,而 JavaScript 组织模块的主要方式是 function。

这些先进的语言的组织单位可以层层包含,就像文件系统的目录结构一样。Rust 中的组织单位是模块(Module)


mod nation {

    mod government {

        fn govern() {}

    }

    mod congress {

        fn legislate() {}

    }

    mod court {

        fn judicial() {}

    }

}


访问权限

Rust 中有两种简单的访问权:公共(public)和私有(private)。

默认情况下,如果不加修饰符,模块中的成员访问权将是私有的。

如果想使用公共权限,需要使用 pub 关键字。

对于私有的模块,只有在与其平级的位置或下级的位置才能访问,不能从其外部访问。

实例

mod nation {

    pub mod government {

        pub fn govern() {}

    }


    mod congress {

        pub fn legislate() {}

    }

   

    mod court {

        fn judicial() {

            super::congress::legislate();

        }

    }

}


fn main() {

    nation::government::govern();

}


mod back_of_house {

    pub struct Breakfast {

        pub toast: String,

        seasonal_fruit: String,

    }


    impl Breakfast {

        pub fn summer(toast: &str) -> Breakfast {

            Breakfast {

                toast: String::from(toast),

                seasonal_fruit: String::from("peaches"),

            }

        }

    }

}

pub fn eat_at_restaurant() {

    let mut meal = back_of_house::Breakfast::summer("Rye");

    meal.toast = String::from("Wheat");

    println!("I'd like {} toast please", meal.toast);

}

fn main() {

    eat_at_restaurant()

}



use 关键字

use 关键字能够将模块标识符引入当前作用域:

实例

mod nation {

    pub mod government {

        pub fn govern() {}

    }

}

use crate::nation::government::govern;


fn main() {

    govern();

}


因为 use 关键字把 govern 标识符导入到了当前的模块下,可以直接使用。

这样就解决了局部模块路径过长的问题。

当然,有些情况下存在两个相同的名称,且同样需要导入,我们可以使用 as 关键字为标识符添加别名:

实例

mod nation {

    pub mod government {

        pub fn govern() {}

    }

    pub fn govern() {}

}

   

use crate::nation::government::govern;

use crate::nation::govern as nation_govern;


fn main() {

    nation_govern();

    govern();

}


Rust 面向对象

下面建造一个完整的类:

second.rs

pub struct ClassName {

    field: i32,

}


impl ClassName {

    pub fn new(value: i32) -> ClassName {

        ClassName {

            field: value

        }

    }


    pub fn public_method(&self) {

        println!("from public method");

        self.private_method();

    }


    fn private_method(&self) {

        println!("from private method");

    }

}

main.rs

mod second;

use second::ClassName;


fn main() {

    let object = ClassName::new(1024);

    object.public_method();

}


Rust 并发编程

Rust 中通过 std::thread::spawn 函数创建新线程:

实例

use std::thread;

use std::time::Duration;


fn spawn_function() {

    for i in 0..5 {

        println!("spawned thread print {}", i);

        thread::sleep(Duration::from_millis(1));

    }

}


fn main() {

    thread::spawn(spawn_function);


    for i in 0..3 {

        println!("main thread print {}", i);

        thread::sleep(Duration::from_millis(1));

    }

}


在 Rust 中,impl 块用于为类型实现功能,而 for 关键字用于指定 impl 块所针对的具体类型

语法:

impl <Trait> for <Type> {

    // Trait 方法的实现

}

<Trait> 是要实现的 trait 的名称。

<Type> 是要为其实现 trait 的类型的名称。

作用:

for 关键字将 impl 块与特定的类型关联起来,使得该类型能够使用 trait 中定义的方法。

示例:


struct Circle {

    radius: f64,

}


trait Area {

    fn area(&self) -> f64;

}


// 为 Circle 类型实现 Area trait

impl Area for Circle {

    fn area(&self) -> f64 {

        std::f64::consts::PI * self.radius * self.radius

    }

}


fn main() {

    let circle = Circle { radius: 5.0 };

    println!("Circle area: {}", circle.area()); // 使用 Area trait 中的 area() 方法

}

在这个例子中:


我们定义了一个 Circle 结构体和一个 Area trait。

Area trait 中定义了一个 area() 方法,用于计算面积。

我们使用 impl Area for Circle 语句为 Circle 类型实现了 Area trait。

在 impl 块中,我们实现了 area() 方法,用于计算圆形的面积。

最后,在 main() 函数中,我们创建了一个 Circle 实例,并调用了 area() 方法来计算圆形的面积。

总结:


for 关键字在 impl 块中用于指定要为其实现 trait 的具体类型,从而将 trait 的功能应用于该类型。






2022年末 Rust权威编程语言入门教程

点击查看原视频



最新最全Rust编程语言入门教程

点击查看原视频



Rust编程语言入门教程

点击查看原视频



Rust UI库

在 Rust 生态系统中,有多个流行的 UI 库可供选择。以下是一些使用较为广泛的 UI 库:

egui: 一个简单、快速、可移植的即时模式 GUI 库。它使用 Rust 编写,可以轻松地创建跨平台的用户界面。

druid: 由 Rust 团队成员开发的一个现代化、跨平台的原生 GUI 库。它强调简单性、可组合性和高性能。

iced: 一个跨平台的 GUI 库,专注于简单性和类型安全。它借鉴了 Elm 的思想,提供了声明式的 API 和响应式的编程模型。

gtk-rs: Rust 绑定的 GTK 库,可以使用 Rust 编写 GTK 应用程序。GTK 是一个成熟、跨平台的 GUI 工具包。

Tauri: 一个使用 Rust 和 Web 技术构建跨平台桌面应用的框架。它允许使用 HTML、CSS 和 JavaScript 创建用户界面,同时利用 Rust 的性能和安全性。

Azul: 一个用 Rust 编写的跨平台 GUI 框架,旨在提供一致的开发体验和原生的性能。它使用即时模式渲染,支持 CSS 样式和 SVG。

这些只是 Rust 中一部分流行的 UI 库,还有其他一些库也在不断发展和完善中,如 Moxie、Relm 等。选择哪个 UI 库取决于你的具体需求、目标平台以及个人偏好。建议你研究和对比几个库,选择最适合你项目的那个。



一个使用 egui 创建简单计数器应用的例子:


use egui::{CentralPanel, CtxRef, Labelable, Ui};


struct MyApp {

    counter: i32,

}


impl Default for MyApp {

    fn default() -> Self {

        Self { counter: 0 }

    }

}


impl MyApp {

    fn new(cc: &eframe::CreationContext<'_>) -> Self {

        Default::default()

    }

}


impl eframe::App for MyApp {

    fn update(&mut self, ctx: &egui::CtxRef, _frame: &mut eframe::Frame) {

        CentralPanel::default().show(ctx, |ui| {

            ui.heading("Counter App");

            ui.horizontal(|ui| {

                if ui.button("-").clicked() {

                    self.counter -= 1;

                }

                ui.label(self.counter.to_string());

                if ui.button("+").clicked() {

                    self.counter += 1;

                }

            });

        });

    }

}


fn main() {

    let app = MyApp::default();

    let native_options = eframe::NativeOptions::default();

    eframe::run_native(Box::new(app), native_options);

}

这个例子创建了一个简单的计数器应用:


我们定义了一个 MyApp 结构体,包含一个 counter 字段用于存储当前计数值。

实现了 Default trait,提供了 MyApp 的默认值。

实现了 eframe::App trait 的 update 方法,定义了应用的 UI 布局和交互逻辑。

在 update 方法中,我们使用 CentralPanel 创建了一个居中的面板,并在其中添加了标题、减号按钮、计数值标签和加号按钮。

当减号按钮被点击时,计数值减 1;当加号按钮被点击时,计数值加 1。

在 main 函数中,我们创建了 MyApp 的实例,并使用 eframe::run_native 启动应用。

运行这个例子,你将看到一个居中的计数器应用,可以通过点击加号和减号按钮来增减计数值。


这只是一个简单的示例,egui 还提供了许多其他的 UI 组件和布局方式,可以用来创建更复杂的用户界面。你可以参考 egui 的文档和示例来进一步了解它的功能和用法。














Top