rust 语法小册子
Rust语法速查小册
1. 数据结构
通过关键字定义的数据类型和内存位置
struct S{}
定义一个命名成员的结构体struct S {x:T}
定义一个结构体,成员名为x,成员类型为Tstruct S(T)
定义元组类型结构体,成员.0
类型为Tstruct S
定义零长单元结构体,不占空间哦
enum E{}
定义一个枚举类,enum E{A, B(), C{} }
定义各种类型枚举,可以是单元A,元组B,或者结构Cenum E {A=1}
如果变量只是单元,允许赋值,如FFI使用
union U{}
unsafe 类C联合体,为了FFI兼容static X: T = T();
有'static
声明周期的全局变量,单一内存位置const X : T = T();
定义常量let x: T;
定义栈T bytes。一次分配,不可变let mut x:T;
允许可变的和可变借用x = y;
移动y到x,如果T类型没有实现Copy,那么y将变为不可用,如果实现了Copy,那么将y拷贝给x。
创建和获取结构体数据,可一些siglic类型
S {x:y}
创建struct S{}
或enum E::S{}
设置y给成员xS {x}
用局部变量x直接赋值S {..s}
将其余变量设置为s的S {0:x}
类似S(x)
设置.0
成员值S(x)
创建S(T)
或者enum E::S()
S
如果S为单元struct S;
或者enum E::S
E::C {x:y}
类似()
空元组,即使文本又是类型,(x)
括号表达式,(x,)
元组单个元素,(S,)
元组单个元素[S]
未定义长度的数组类型,如切片,不能在栈上定义。[S; n]
定长数组,长度为n,元素类型为S[x; n]
数组实例,长度为n,每个元素都是x[x, y]
数组元素,值为x,yx[0]
集合索引,实现了Index, IndexMut的traitx[..]
所有元素,给个范围
a..b
给了范围[a, b)
..b``(-∞,b)
,..=b``(-∞,b]
2.引用和指针
不属于自己所有内存授权
&S
共享引用,空间可以被任何&s
所有&[S]
切片的引用,包含了地址和长度&str
string切边的引用,包含地址和长度&mut S
允许可变的引用,唯一性(&mut [S], &mut dyn S
)&dyn T
trait object引用,包含地址和vtable
&s
共享借用&mut s
排它借用允许改变
*const S
不可变裸指针w/o内存安全*mut S
可变裸指针&raw const s
不通过引用创建裸指针,ptr::addr_of!()
&raw mut s
同样都是可变的
ref s
用作绑定引用类型let ref r = s;
相当于let r = &s;
let S {ref mut x} = s;
可变绑定引用let x = &mut s.x;
*r
解引用或者指向的内容*r = s;
如果r是可变的引用,move或者copys给目标内存s = *r;
如果r实现了Copy,则将*r
复制给s,如果*r
没实现Copy将会moves = *my_box
如果没实现了Copy则也会move
'a
在静态分析一个流程的一个声明周期参数&'a S
只接受持有s的地址,这个地址存在'a
或更长&'a mut S
一样,只是可变struct S<'a> {}
通知S将会包含声明周期'a
地址。S创建来决定'a
trait T<'a>{}
fn f<'a>(t: &'a T)
'static
静态声明周期
3.函数和行为
定义代码单元和他们抽象
trait T {}
trait T: R {}
T是supertraitR的subtrait。任何S必须在实现T之前先实现Rimpl S{}
方法impl T for S {}
实现类型S的Timpl !T for S {}
关闭autotraitfn f() {}
fn f() -> S{}
fn f(&self) {}
struct S(T);
const fn f() {}
编译时常量函数const X:u32 = f(Y)
async fn f() {}
异步函数async fn () -> S{}
async {x}
fn() -> S
函数指针Fn() -> S
可调用的闭包FnMut, FnOnce
||{}
|x|{}
|x|x+x
move |x| x + y
闭包获得捕获的所有权,y转移到了闭包return ||true
返回一个闭包
unsafe
unsafe fn f() {}
unsafe trait T {}
unsafe { f();}
unsafe impl T for S {}
4.控制流
while x {}
loop {}
for x in inter {}
if x {} else {}
'label: loop {}
break
break x
x作为表达式值,loop中使用break 'label
或者break 'label x
continue
和continue 'label
x?
如果x式Err或者None则返回x.await
async使用return x
函数中的先返回x.f()
X::f()
X::f(&x)
X::f(&mut x)
X::f()
<X as T>::f()
调用traitT::f()
方法
5.代码结构
mod m {}
mod m;
定义一个模块,从m.rs
或m/mod.rs
中获取a::b
::b
搜索crate root或external prelude; global pathcrate::b
crate root中找bself::b
当前mod找bsuper::b
父模块找b
use a::b;
这个范围可直接使用buse a::{b, c};
use a::b as x;
use a::b as _;
use a::*;
pub use a::b;
pub T
pub(crate) T
当前crate可访问pub(super) T
pub(self) T
pub(in a::b) T
祖先a::b可见
extern crate a;
依赖外部crate,可以直接使用use a::b
extern "C" {}
依赖外部ABIextern "C" fn f() {}
定义可被外部访问的FFI
6.类型重命名和转换
type T = S;
Self
self
&self
&mut self
self: Box<Self>
S as T
S as R
x as u32
7.宏和属性
-
m!()
宏调用,也可以m!{}
,m![]
根据具体宏 -
#[attr]
外部属性 -
#![attr]
内部属性 -
$x:ty
宏捕获,:..fragment
声明$x允许的内容 -
$x
宏替换,使用上面的声明内容 -
$(x),*
宏重复,零或更多$(x),?
0或1$(x),+
, 1或更多$(x)<<+
分隔符不是,
这里是<<
8.样式匹配
match m {}
let S(x) = get()
let S {x} = s;
let (_, b, _) = abc;
let (a, ..) = abc;
let (.., a, b) = (1, 2)
let s & S{x} = get();
将s绑定到S,同时x绑定到是s.xlet w @ t @ f = get();
存放3个复制get()结果,分别给w,t,flet Some(x) = get() {}
不能工作,使用if let
if let Some(x) = get() {}
while let Some(x) = get() {}
fn f(S {x} : S)
函数参数也可以项let一样将s.x给f(s)
语法糖
match get() { Some(x) => {}, _ => () }
arm匹配
E::A => {}
匹配枚举类型AE::B(..) => {}
匹配枚举元组变量,忽略所有索引E::C {..} => {}
匹配结构体变量C,忽略所有成员S {x:0, y:1} => {}
匹配结构体(只接收s.x=0和s.y=1)S {x: a, y: b} => {}
匹配结构体任何结构体,绑定s.x给a,s.y给bS{x, y} => {}
同样,但是简写方式
S{..} => {}
匹配结构体有任何值的_ => {}
匹配剩余的0 | 1 => {}
匹配可选,或者模式E::A | E::Z => {}
E::C {x} | E::D {x} => {}
Some(A | B) => {}
也可以多层嵌套
(a, 0) => {}
匹配任何a和第二个是0的元组[a, 0] => {}
切片样式,匹配数组第一个任何为a,第二个为0[1, ..] => {}
[1, .., 5] => {}
[1, x @ .., 5] => {}
中间的绑定为x[a, x @ .., b] => {}
1 .. 3 => {}
1 ..= 3 => {}
1 .. => {}
x @ 1..=5 => {}
绑定匹配给x
Err(x @ Error {..}) => {}
嵌套绑定S{x} if x > 10 => {}
条件匹配,条件要为true
9.模板和约束
S<T>
S<T:R>
trait bound R必须是具体的trait,T必须实现RT: R, P:S
T: R, S
这个是不对的,要写成T: R + S
T: R + 'a
T: ?Sized
可选退出预定义的trait边界T: 'a
如果T是引用,必须长于'a
T: 'static
'b : 'a
'b
周期大于等于'a
S<const N: usize>
常量约束S<10>
使用方法S<{5 + 5}>
表达式必须放入大括号中
S<T> where T: R
和S<T: R>
相同,看起来好点S<T> where u8: R<T>
可以用来条件称述
S<T = R>
默认参数S<const N: u8 = 0>
S<T = u8>
S<'_>
推断匿名声明周期,如果明显的让编译器计算出S<_>
推断匿名类型let x: Vec<_> = iter.collect()
S::<T>
调用地方消除歧义f::<u32>()
trait T<X> {}
可以有多个impl T for S(每个X)
trait T { type X;}
关联类型,只能一个impl T for S
type X = R;
在S中设置关联类型impl T for S {type X = R;}
impl<T> S<T> {}
实现任何类型T在S<T>
,这个T类型参数impl S<T> {}
例如S<u32>
fn f() -> impl T
fn f(x: &impl T)
fn f(x: &dyn T)
fn f() where Self::R;
在trait T{}
,让f可认识类型为impl R
fn f() where Self::Sized;
使用 Sized 可以选择 f 退出 dyn T trait object vtable,启用 trait objfn f() where Self::R {}
其他 R 有用的 w. dflt.方法(反正非dflt.需要拔)
10.higher-ranked 项目
实际类型和traits,某个内容的抽象,通常生命周期
for<'a>
higer-ranked boundstrait T: for<'a> R<'a> {}
fn (&'a u8)
for<'a> fn(&'a u8)
fn (&'_ u8)
fn(&u8)
dyn for<'a> Fn(&'a u8)
dyn Fn(&'_ u8)
dyn Fn(&u8)
11.字符串和字符
...
string类型,UTF-8,包含\n
r"..."
raw string不会有\n
r#"..."#
可以包含"
#
数量可变的b"..."
byte string ASCII类型[u8]
,不是stringbr"...",br#"..."#
raw byte string ASCII类型[u8]
- '🦀'字符char类型,占4字节
b'x'
ASCII byte
12.文件注释
///
types, traits和functions的doc文档信息//!
模块的开始文件 doc的内联行//
行注释/*...*/
块注释/**..*/
外部块注释/*!...*/
内部块注释
13.杂项
!
永不返回_
未命名配置let _ = x;
x移出这个范围
_x
1_234_567
1_u8
0xBEEF, 0o777, 0b1001
r#foo
x;