Rust语言一些针对初学者的编程技巧

2020-07-1709:02:08编程语言入门到精通Comments3,375 views字数 3145阅读模式

Rust也有缺点就是学习曲线比较曲折,对初学者不是那么友好。本文虫虫给大家分享一下Rust语言的一些针对初学者的编程技巧,希望对大家有所帮助。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

Racer,Clippy,rustfmt和fix文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

这是非常好用的一组工具。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

Racer用来帮助你对rust代码进行补全。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

可以使用cargo安装racer使用:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

cargo install racer文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

racer需要先获取Rust源码路径,可以通过rustup获取源码:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

rustup component add rust-src文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

rustup update可以随时获取最新代码文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

Clippy可以在代码中捕获各种lints,并检查代码是否符合rust惯用写法,地道不地道、高效不高效?。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

要安装Clippy,请运行rustup component add clippy文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

然后在工作区中运行Clippy:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

cargo clippy --tests -- -W clippy::cargo文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

可以通过执行命令行参数或者clippy.toml配置文档来制定clippy的检查事项:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

Rust语言一些针对初学者的编程技巧

rustfmt是一种根据风格样式来格式化Rust代码的工具。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

安装rustfmt,使用:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

rustup component add rustfmt文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

然后工作区中运行rustfmt:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

cargo fmt。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

同样的可以用rustfmt.toml来配置rustfmt的风格:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

Rust语言一些针对初学者的编程技巧

cargo fix工具可以自动修复编译器中警告项。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

同名宏,函数和类型文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

熟悉Rust的同学可能知道,Rust最强大的功能之一就是宏,比如Hello,Chongchong范例中:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

fn main() {文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

println!("Hello,Chongchong");文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

}文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

println!()就是一个宏。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

在Rust我们可以使用相同的名称声明一个宏,一个函数和一个类型,然后可以用一条import语句将他们引入其他文件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

dbg!宏文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

Rust语言一些针对初学者的编程技巧

DBG宏可用于显示表达式和值的计算过程,可以用来快捷调试部分代码表达式。比如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let a = 2;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

et b = dbg!((a+3) * 2) + 1;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

assert_eq!(b, 11);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

上面的代码将打印出:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

[dbg.rs:3] (a + 3) * 2 = 10文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

错误类型转换文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

直接使用rust的错误处理可能不够灵活,使用unwrap(),当出现错误时候就会触发panic,导致程序挂掉,很多时候这不是我们所期望的。下面是一个例子,文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

fn main() {文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let path = "/tmp/example";文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

println!("{}", read_file(path));文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

}文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

fn read_file(path: &str) -> String {文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

std::fs::read_to_string(path).unwrap()文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

}文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

如果/tmp/example,不存在就会触发panic错误:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Os { code: 2, kind: NotFound, message: "No such file or directory" }', ok.rs:7:5文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

好在我们可以使用?,通过?运算符可以将错误返回转化为了Err(From::from(err))和Ok(ok)分支处理,这样错误可以转换为自动类型。部分代码如下,可以自定义错误消息CustomError:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

fn main() -> std::result::Result<(),CustomError>{文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let path = "/tmp/example ";文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let v = read_file(path)?;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

Ok(())文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

}文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

模块化测试文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

试想,你项目测试结构如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

tests/文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

aaa.rs文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

bbb.rs文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

测试时,这些每个都会被编译为单独的二进制文件,这会花费大量编译时间和空间。可以将这些测试文件作为模块添加到一个测试中,这样就只生成一个二进制文件。新测试结构如下所示:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

tests/文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

all/文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

mod.rs // mod aaa; mod bbb;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

aaa.rs文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

bbb.rs文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

mod.rs // mod all;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

使用该技巧,能够大大减少编译时间,节省时间和空间提高效率。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

当然它也有缺点那就是不能对单个文件进行测试,而只能统一编译该文件。即使只更改了一个测试文件,它也要编译完整项目文件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

编译器缓存文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

Rust编译器cargo只支持工作区内部项目间的编译缓存,不支持工作区之间的缓存。对于多个工作区的多个项目使用相同的依赖关系,就要额外花费时间各自编译。我们可以借助cargo缓存工具sccahe来解决这个问题。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

sccache是类似于ccache的cargo的编译器缓存,编译该依赖关系一次,然后在所有项目中就可以重复使用。可以大大节省编译时间和磁盘空间。sccache除了可以把编译构建存在本地外,也支持存在云端,比如AWS S3或者GCS等。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

可以使用操作系统包管理器或者cargo来安装sccache:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

cargo install sccache。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

windows下可以使用文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

scoop install sccache文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

要使用sccache缓存rust编译,需要在cargo配置文件(~/.cargo/config)中定义build.rustc-wrapper:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

[build]文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

rustc-wrapper = "/path/to/sccache"文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

也可以在编译时候直接设置RUSTC_WRAPPER环境变量:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

RUSTC_WRAPPER=/path/to/sccache cargo build文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

避免不必要的克隆文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

在rust中对变量调用.clone()会为其创建数据的副本。创建数据副本需要消耗很多内存资源,因此大多数情况下会影响程序的性能,应避免使用。通常,可以将使用应用引用而非创建clone。例如:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

fn main() {文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let x = Foo::new();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

func(x.clone());文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

func(x.clone()); // 该克隆是非必须的文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

fn main() {文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let x = Foo::new();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

func(x.clone());文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

func(x); // This will work fine because you do not need文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

// to use x after this call文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

}文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

使用:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

fn main() {文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let x = Foo::new();文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

func(&x);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

func(&x);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

}文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

枚举大小受最大成员限制文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

枚举的大小使其能够容纳其最大的变体。因此,建议在枚举内使用类似大小的变体,以避免内存布局不理想。如果需要,可以考虑将较大的变量Box化。考虑以下示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

enum Foo{文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

A(u64),文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

B([u64; 1000]),文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

}文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

enum FooBoxing {文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

A(u64),文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

B(Box<[u64;1000]>)文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

}文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

fn main() {文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let x = Foo::A(0); // 大小8008 字节文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let y = FooBoxing::A(0); // 16字节文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

println!("Foo size {:?}", std::mem::size_of_val(&x));文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

println!("FooBoxing size {:?}", std::mem::size_of_val(&y));文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

}文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

在上面的示例中,枚举Foo的变体A的大小比变体B小得多,但用于两个变体的内存布局将相同,因此,当使用变体A时,其性能将不理想。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

标准交换功能文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

rust swap函数允许直接交换两个变量,而无需创建一个临时变量。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

use std::mem;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let mut x = 5;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

let mut y = 42;文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

mem::swap(&mut x, &mut y);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

assert_eq!(42, x);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

assert_eq!(5, y);文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

结论文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

Rust语言中有很多使用的技巧可以参考。希望本文抛砖引玉,给大家一些启发。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/ymba/19749.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/ymba/19749.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定