4.9 Borrow 和 AsRef
Borrow和AsRef特性特性很相似,但是不一样.这里有一个快速的关于两者的回顾.
4.9.1 Borrow
Borrow特性是当你写了一个数据结构,然后你想让一个它的所有者或者借用者类型作为同义词对象来使用.
例如,HashMap就有一个get方法使用了Borrow:
fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V>
where K: Borrow<Q>,
Q: Hash + Eq
这个签名非常复杂.K参数是我们感兴趣的点.它代表着一个HashMap的参数:
struct HashMap<K, V, S = RandomState> {
K参数就是HashMap使用的key.所以,再看一下get()的签名,我们可以试用get()函数,当key实现了Borrow<Q>时.那样,我们可以生成一个使用String作为key的hashMap,但是当我们搜索的时候使用&str.
use std::collections::HashMap;
let mut map = HashMap::new();
map.insert("Foo".to_string(), 42);
assert_eq!(map.get("Foo"), Some(&42));
这是因为标准库为String类型实现了impl Borrow<str>.
对大部分类型来说,当你需要一个拥有的或借用的类型时,一个&T就足够了.而Borrow高效的地方在于当有多个借用的值发生时.切片就是其中一种场景:你可以获得一个&[T]或者&mut [T].如果我们希望同时获得这两个类型:
use std::borrow::Borrow;
use std::fmt::Display;
fn foo<T: Borrow<i32> + Display>(a: T) {
println!("a is borrowed: {}", a);
}
let mut i = 5;
foo(&i);
foo(&mut i);
输出是俩个:a is borrowed: 5
4.9.2 AsRef
AsRef是一个习惯特性.它用于在泛型代码中将值转换为引用.像这样:
let s = "Hello".to_string();
fn foo<T: AdRef<str>>(s: T) {
let slice = s.as_rf();
}
4.9.3 我该用那个?
我们可以看到他们很像:他们都可以处理所有的或借用的类型.但是有一点不同.
当你需要抽象不同类型的借用时,使用Borrow,或者你要创建一个数据结构用相同的方法来处理所有的或借用的值,例如hashing和比较.
当你需要把值直接转化为引用的时候,使用AsRef,并且你在写泛型代码.
4.10 发布渠道
Rust工程使用一个概念叫"发布渠道"来管理它的发布.当你选择使用哪种版本的Rust的时候,理解它就很重要.
4.10.1 概览
有三种发布渠道:
nightly
beta
stable
每夜发布板每天都会生成.每6周,最后一个每夜发布板升级为beta版.那时,它将只收到patch来解决严重问题.6周之后,beta版升级为稳定版,然后变成下一个1.x版本.
这个过程是并行的.所以每过6周,在同一天,都会有nightly,beta,stable发布.当1.x发布后,同时,1.(x+1)-beta发布,nightly也会变成1.(x+2)-nightly.
4.10.2 选择一个版本
总的来说,除非你是特别的原因,你应该选择stable版本.这个版本适用于广大受众.
然而,你可以选择使用nightly版本,取决于你对Rust的感兴趣程度.代价是这样的:nightly版本中,你可以使用不稳定的,新的Rust特性.然而,不稳定的特性也会改变,所以任何新的nightly版本都可能是你的代码崩溃.如果你使用stable版本,你不能体验实验性的特性,但是下一个stable版本发布的时候不会对你的代码造成严重影响.
4.10.3 使用CI来帮助构建Rust生态系统
那么beta版本呢?我们鼓励所有的Rust程序员使用stable版本的同时也测试一下beta版本.在他们持续的系统环境中使用beta版.这会帮助我们的团队,提出预警,以免发生意外的倒退.
另外,测试nightly版本可以更快的捕获倒退,如果你不介意编译3次,你可以测试所有的版本.