Basics
Basics
编译和运行工具
cargo创建新项目目录:
目录会自动git仓库化,其中包含一个src文件夹和一个toml文件,src目录下有一个main.rs文件。使用cargo new --vcs=git
似乎可以避免初始化为git仓库。
TOML文件使用的是专用的TOML格式,用来描述cargo的配置选项。初始有[package]和[dependencies]两个段,package段包含对当前包的信息描述,dependencies段包含这个包的依赖。Rust把包称为crates
。
src目录用来包含所有的代码文件。
构建运行cargo项目(假设项目名为hello_cargo):
https://learnku.com/rust/t/39451
VSCODE中安装一个RUST扩展即可,在设置中修改rust-client.channel为stable;设置editor.formatOnSave为true可以在保存时格式化代码(有rust-fmt的话)
Hello world
引用外部crate时,需要修改toml文件中的[dependency]段。例如我们需要生成随机数,要用到rand
crate,于是我们在toml文件中添加:
然后执行构建,cargo就会拉取兼容的crates。一旦拉取,cargo不会主动再更新,要把依赖更新到最新版本,需要执行更新指令:
然后可以使用随机数生成:
这里的Rng
是一个trait,定义了随机数生成相关的方法。
rust允许将同一个变量名多次绑定到不同类型的值上去(类似python),称为shadow。
显式指定变量类型的方法为let [varname]: [typename] = [value];
可变性mutability
shadowing
重复使用 let 以同一变量名创建变量时,新变量覆盖旧变量(或者说该变量名被绑定到了新值上),这种覆盖称为 shadowing。(python 支持类似的机制)shadowing 会随着新变量的销毁(如程序退出新变量的 scope)而失效,此时该变量名将重新绑定到旧值。
shadow 机制中,同一变量名可以绑定到不同的值类型。而通过将变量声明为 mut 以能够修改其值时,变量的类型是无法改变的。
ownership
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.
超出作用域scope的变量拥有的内存会直接被drop掉。下面讨论各种情况:
有drop trait的变量无法附加copy trait。
函数传参和返回值时发生的事情类似。
但大多数时候我们希望变量把值传给函数后还能继续使用,如果让函数在返回值时再把所有权通过赋值退回来就太麻烦了。因此 rust 设计了 reference 机制。创建一个 reference 的过程称为 borrowing。
为此带来的代价是,borrow来的值默认无法被修改(immutable)。为了能够修改参数,需要把parameter和argument声明为mut的。
可变引用有一些奇怪的规则:
同一块数据在任一时刻最多只能有一个可变引用(持有者本身不算)
如果一个可变引用被销毁了,那之后就可以创建新的可变引用
同一块数据在任一时刻不能同时拥有可变和不可变的引用
同一块数据可以拥有多个不可变引用
基本类型
基本类型分为scalar和compound。这些类型都是在栈上分配的。
有copy trait的类型有所有scalar和tuple。
scalar包括:
整数值(i32, u32等,i表示有符号,u表示无符号,后面的数字表示位数;特别地
isize
和usize
的宽度取决于机器架构)浮点(f64, f32,默认f64)
布尔值(
true
,false
)字符(rust的字符是unicode编码,4字节宽)
compound包括:
tuple
使用圆括号括起多个类型,长度不可变:
可以被destructure,拆到多个变量,这个语法类似于python
还可以用点号来索引tuple的元素
这两种复值方法都不会破坏tuple本身,应该是相当于把值拷贝出来了
array
使用方括号扩起多个相同类型的值,长度不可变;可变的是vector
数组元素用方括号索引,运行时越界访问会抛出out of bounds异常
循环遍历数组带来的索引合法性检查会影响性能,因此推荐的是使用iter()方法遍历。参见控制流部分。
数组可以切片(slice),可参考字符串一节,其类型为
&[EleType]
,切片语法同字符串
基本运算符
函数
rust习惯使用snake case命名函数,即小写加下划线分隔
使用fn关键字可以定义一个函数。函数定义位置的先后不影响调用(和C不同)
严格来说parameter是函数参数,而argument是传入的实际值,不过实际常混用。rust的函数定义方式:
return语句依然可以使用,一般用于提前返回。
statement和expression
函数定义、变量赋值等都属于statement;
除了一般意义上的表达式外,{ }也是一个表达式。
控制流
if表达式(注意是一个表达式expression)实现一个条件分支,条件表达式不需要加括号,其返回值必须是bool变量(而不能是int之类)。
loop表达式实现一个无限循环。
使用break
可以跳出循环,还可以顺带返回值:
while结构也是有的:
for循环遍历区间:
for循环可以用来在一个集合结构上迭代,这种迭代比较快速而安全:
match语句类似C的switch,将表达式的结果和每个分支的pattern比较。(表达式的括号并不是必要的)
关于match的介绍详见 OOP - match,pattern & if let.
Math
随机数
比较
Last updated
Was this helpful?