Rust语言相关

cc 发布于2018年10月26日 ∣ Rust ∣ 约1849字 · 需4分钟 阅读()

轻度用户

语法比较奇特,与常规语言出入比较大 编译时间花时间比较长,从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 () = “"; 抛出错误会提示类型