Rust语言相关
轻度用户
语法比较奇特,与常规语言出入比较大 编译时间花时间比较长,从go过来有点无法忍受 编译时下载依赖有点js,需要下载一堆的包,看着难受,等得难受
没有运行时,编译出来的体积相对比较少
1#安装
2curl https://sh.rustup.rs -sSf | sh
3#版本查看
4rustc -V
5#升级命令
6rustup upgrade
cargo,项目/包管理
1--bin表示生成可执行文件
2cargo new projname --bin
3cargo search pkgname
4cargo build 在项目target/debug目录下创建执行文件
5cargo update
6cargo run
依赖安装区别于其他。cargo install pkg 这是安装二进制文件的,而不是安装依赖包。需要手动在config.toml文件中配置,可以是版本号,可以是git项目,也可以是本地路径。运行时才去会下载
1[dependencies]
2pkg-name="pkg-version or *"
3pkg-name={git = "git repo", rev = "bfabc843ef2"} #可能指定参数
4pkg-name={path = "./utils"} #支持绝对路径,相对路径
格式化打印
1Debug ("{:?}", xx)
2Display ("{}", xx)
引用
模块与关联函数都使用::调用,只有实例方法用.调用
类型转换
rust不能隐式转换类型,但是可以使用as显示使用
可空处理
内置Option
错误处理
分可恢复与不可恢复,不可恢复直接panic!宏处理。不像go什么错误都可defer捕获 没有Exception。只有Result<T,E>类型作为返回值处理。貌似错误都是可预见的?!
可恢复错误的不可恢复处理,使用unwrap()不指定错误或expect(msg: &str)指定错误处理
Result? 要么取出非异常值,要么返回异常
Err有kind方法来判断错误类型
if let可做类型匹配
1let f = File::open("hello.txt");
2if let Ok(file) = f {
3 // 成功打开文件处理
4}else {
5 // 打开失败
6}
所有权,移动与借用
概念的引入是为了内存的高效安全释放 代码运行时的数据会放到stack或heap中,stack是先进后出,存放的固定大小的数据。未知大小可大小可变数据会放到heap中,在heap中找一个足够大的位置并返回指针以写入数据,stack不用找直接写入。
字符在存储的时候分成两部分,指针描述因为有固定大小存在stack,内容存在heap中。而数值/布尔/字符及对应的元组只存在于stack中,出栈的时候自动丢弃不需要处理。这里可以看到stack的数值可以重复,而heap中只存放一份。所以在let赋值时非copy类型变量会被占居所有权
所有权规则:1、每个变量值都有一个变量既所有者;2、同一时间一个值只有属于一个变量;3、当变量生命周期结束对应的值会被丢弃
将变量传递给一个函数时跟赋值一样,copy类型的变量仍然可用,非copy类型变量则被move到函数内,不再可用。
函数返回可以传递所有权,
传值为移动,传指针为借用 借用没有发生所有权移动,借用的只能用不可修改数据,除非变量本身可以修改
特性trait
类似于接口。同一个类可以实现多个特性,
函数返回特征时,编译器不确定到底用哪个实现,这个时候用Box::new(xx)返回
特征超集,类似继承
生命周期注释
因为生命周期的缘故,函数在返回值的时候可能会返回一个过期的引用。编译时直接提示出错
最大的作用在于多个引用的泛型生命周期的标注,方便编译识别,编译器没有足够智能识别所有场景
静态生命周期 生命周期显示声明 ‘a,‘b 用’加字符的形式, foo<‘a> fu bar<‘a> {}
还可以绑定到泛型类型说明中 &‘a var
fu foo<‘a:‘b, ‘b>(&‘a i32, &‘b i32) //生命周期’a至少与’b一样长
‘static存在于整个程序运行时期
其实每个函数方法trait都要标注生命周期的,只有有些简单的编译器可以自己判断,不需要再手动写那些繁琐的生命周期注释
3条规则 一个输入生命周期,多个输入多个生命周期 一个输入一个输出,输出跟输入一样? 多个输入生命周期,其中一个是&self或&mut self
泛型
闭包
宏macro
以!结尾的函数。与c不同的是生成语法树而不是文本 使用macro_rules!定义 参数可以是接收多种类型 macro_use有两个目的,一个是让一个模块的宏的生命同期不会随着模块结束而结束,这个是在模块内部定义宏时使用。另一个是从另外一个crate中导入宏时给宏添加属性
条件编译
all(), any(), not() cfg!(), cfg_attr!()
包引用
extern crate lib; // 非cargo项目需要这步操作 // 可以取别名 extern crate lib as mylib use lib::xxx::yyy; // 现在可以使用yyy不用再加完整路径
异常处理
panic vs Option,option还有map可以chain Option.unwrap, 为空时直接panic Result
储存概念
所有的值默认分配stack,所有的值也可以box在heap上分配内存。Box::new()返回的指针 可增长String与vectors stack空间由操作系统自动分配释放,heap需要手动申请翻译,stack空间有限,heap有很大的自由区
QA
怎么快速查看类型 let () = “"; 抛出错误会提示类型