一切正常。 先打印 person 的全部内容,然后是模式匹配。 但是尝试在函数末尾添加上这行,你会得到一个编译错误:
error[E0382]:use of partially moved value: `person`--> main.rs:18:41|9 |Some(name) => println!("Name is {}", name),|---- value moved here...18 | println!("FullPerson value: {:?}", person);|^^^^^^ value used here after move|= note:move occurs because the value has type `std::string::String`, which does not implement the `Copy` traiterror: aborting due to previous error
注意:这是我使用的Rust编译器1.30.1的错误。 但是,已经有计划来改善这种情况。
问题在于我们已经消耗了 person 的一部分,因此无法打印它。 我们可以通过再次设置来解决此问题。 让 person 参数可变,然后使用默认的None 值填充移动的 person.name:
fnprint_person(mut person:Person) {match person.name {Some(name) =>println!("Name is {}", name),None=>println!("No name provided"), }match person.age {Some(age) =>println!("Age is {}", age),None=>println!("No age provided"), } person.name =None;println!("Full Person value: {:?}", person);}
编译运行,但现在输出结果令人困惑:
Name is AliceAge is 30FullPerson value:Person { name:None, age:Some(30) }
注意最后一行中name的值是None,理想情况下应该是 Some (Alice)。 我们可以做得更好,通过返回 match 中的 name:
person.name =match person.name {Some(name) => {println!("Name is {}", name);Some(name) },None=> {println!("No name provided");None }};
fnprint_person(person:Person) {match person.name {Some(ref name) =>println!("Name is {}", name),None=>println!("No name provided"), }match&mut person.age {Some(age) => {println!("Age is {}", age); age +=1; }None=>println!("No age provided"), }println!("Full Person value: {:?}", person);}
编译器抱怨:age是一个 &mut u32,但是我们试图在其上使用 += :
error[E0368]: binary assignment operation `+=` cannot be applied to type `&mutu32`--> src/main.rs:16:13|16| age +=1;|---^^^^^||| cannot use `+=` on type `&mutu32`|= help: `+=` can be used on 'u32', you can dereference `age`: `*age`
根据编译器的踏实,我们需要采用取消年龄引用。 但又出现一个错误:
error[E0596]: cannot borrow field `person.age` of immutable binding as mutable--> src/main.rs:13:16|7|fnprint_person(person:Person) {|------ consider changing this to `mut person`...13|match&mut person.age {|^^^^^^^^^^ cannot mutably borrow field of immutable bindingerror: aborting due to previous error
同样,编译器准确地告诉我们如何解决这个问题: 使 person 可变。 继续,做出改变,一切都会顺利进行。
error[E0599]: no method named `collect` found fortype `Single<{integer}>` in the current scope--> src/main.rs:12:39|1|structSingle<T> {|---------------- method `collect` not found for this...12|let actual:Vec<u32> =single(42).collect();|^^^^^^^|= note: the method `collect` exists but the following trait bounds were not satisfied: `&mutSingle<{integer}> : std::iter::Iterator`= help: items from traits can only be used if the trait is implemented and in scope= note: the following trait defines an item `collect`, perhaps you need to implement it: candidate #1: `std::iter::Iterator`
error[E0507]: cannot move out of borrowed content--> src/main.rs:21:9|21| self.next|^^^^ cannot move out of borrowed contenterror: aborting due to previous error
哦,对。 我们不能将结果值移出,因为我们的 next 函数只能可变借用 self。 让我们尝试一些模式匹配:
match self.next {Some(next) =>Some(next),None=>None,}
fnnext(&mut self) ->Option<T> {let res = self.next; self.next =None; res}
不,编译器仍然不满意! 我想我们只需要放弃对单一迭代器的宏伟愿景。 我们当然可以作弊:
fnnext(&mut self) ->Option<T> {None}
但是,尽管编译完成,但它在运行时未能通过我们的测试:
thread 'main' panicked at 'assertion failed: `(left == right)` left: `[42]`, right: `[]`', src/main.rs:13:5note: Run with `RUST_BACKTRACE=1` for a backtrace.
error[E0106]: missing lifetime specifier--> src/main.rs:6:58|6|fnget_older_name(person1:&Person, person2:&Person) ->&String {|^ expected lifetime parameter| = help: this function's return type contains a borrowed value, but the signature does not say whether it is borrowed from `person1` or `person2`
我们仍然从编译器得到一个错误,因为我们的返回值没有生命周期。 我们应该选择 a 还是 b? 或者我们可以创建一个新的 c 并尝试一下? 让我们从 “ a” 开始。 我们得到了错误消息:
error[E0623]: lifetime mismatch--> src/main.rs:10:9|6|fnget_older_name<'a, 'b>(person1:&'aPerson, person2:&'bPerson) ->&'aString {|--------------------|| | this parameter and the return type are declared with different lifetimes...
...10|&person2.name|^^^^^^^^^^^^^...but data from `person2` is returned here
这是有道理的: 因为我们的结果可能来自于 person2,我们不能保证 ‘ a 寿命参数小于或等于 ’ b 寿命参数。 幸运的是,我们可以明确地声明,就像我们声明类型实现了一些 traits 一样:
fnmain() {let alice =Person { name:String::from("Alice"), age:30, };foo(&alice);}fnfoo(alice:&Person) {let bob =Person { name:String::from("Bob"), age:35, };let name =get_older_name(&alice, &bob);println!("Older person: {}", name);}
Alice 的生命周期显然比Bob的生命周期要长。 但是,函数签名中生存期的语义是所有值至少具有相同的生存期。 如果他们碰巧活得久一点,没有伤害,没有犯规。
多生命周期参数需求
那么,我们能否举出一个绝对需要多个生存期参数的例子呢? 当然!
fnmessage_and_return(msg:&String, ret:&String) ->&String {println!("Printing the message: {}", msg); ret}fnmain() {let name =String::from("Alice");let msg =String::from("This is the message");let ret =message_and_return(&msg, &name);println!("Return value: {}", ret);}
fnmain() {let name =String::from("Alice");let ret =foo(&name);println!("Return value: {}", ret);}fnfoo(name:&String) ->&String {let msg =String::from("This is the message");message_and_return(&msg, &name)}
现在编译器不高兴了:
error[E0597]: `msg` does not live long enough--> src/main.rs:14:25|14|message_and_return(&msg, &name)|^^^ borrowed value does not live long enough15| }|- borrowed value only lives until here|note: borrowed value must be valid for the anonymous lifetime #1 defined on the function body at 12:1...--> src/main.rs:12:1|12|/fnfoo(name:&String) ->&String {13||let msg =String::from("This is the message");14||message_and_return(&msg, &name)15|| }||_^
fn print_vals(vref: &[u32]) {
let v = *vref;
for i in v {
println!("{}", i);
}
}
编译器又跟我们发脾气了:
error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
--> src/main.rs:7:9
|
7 | let v = *vref;
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u32]`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-sized>
= note: all local variables must have a statically known size
error[E0277]: the size for values of type `[u32]` cannot be known at compilation time
--> src/main.rs:8:14
|
8 | for i in v {
| ^ doesn't have a size known at compile-time
|
= help: the trait `std::marker::Sized` is not implemented for `[u32]`
= note: to learn more, visit <https://doc.rust-lang.org/book/second-edition/ch19-04-advanced-types.html#dynamically-sized-types-and-sized>
= note: required by `std::iter::IntoIterator::into_iter`
error[E0277]: the trait bound `[u32]: std::iter::Iterator` is not satisfied
--> src/main.rs:8:14
|
8 | for i in v {
| ^ `[u32]` is not an iterator; maybe try calling `.iter()` or a similar method
|
= help: the trait `std::iter::Iterator` is not implemented for `[u32]`
= note: required by `std::iter::IntoIterator::into_iter`
fn main() {
let bytearray1: &[u8; 22] = b"Hello World in binary!";
let bytearray2: &[u8] = b"Hello World in binary!";
println!("{:?}", bytearray1);
println!("{:?}", bytearray2);
}