用带有两个字符串字段的struct解释Rust所有权概念


下面代码struct有两个字符串字段:

#[derive(Debug)]
struct Person {
    name: String,
    alias: String,
}
fn main() {
    let person = Person { 
        name: "John".to_string(),
        alias:
"Johan".to_string(),
    };
    print_alias(person.alias);
    println!(
"{:?}", person);
}
fn print_alias(alias: String) {
    println!(
"Person: {:?}!", alias);
}

编译器报错:

error[E0382]: borrow of partially moved value: `person`
  --> src/main.rs:12:22

然而,在这个列表中,我们在print_alias之后添加了一个print语句。

这个程序没有被编译,因为person.alias已经部分进入print_alias,但是我们试图在println!行中将person作为一个整体借用。

事实证明,我们可以部分移动字段--只要确保我们以后不要再尝试使用结构本身。

在这里,我们将两个字段移到两个不同的函数中。

#[derive(Debug)]
struct Person {
    name: String,
    alias: String,
}

fn main() {
    let person = Person { 
        name: "John".to_string(),
        alias:
"Johan".to_string(),
    };
    print_alias(person.alias);
    print_name(person.name);
}

fn print_alias(alias: String) {
    println!(
"Alias: {:?}!", alias);
}

fn print_name(name: String) {
    println!(
"Name: {:?}!", name);
}

输出:

Alias: "Johan"!
Name:
"John"!

我们也可以通过引用来传递这些字段。

#[derive(Debug)]
struct Person {
    name: String,
    alias: String,
}

fn main() {
    let person = Person { 
        name: "John".to_string(),
        alias:
"Johan".to_string(),
    };
    print_alias(&person.alias);
    print_name(&person.name);
}

fn print_alias(alias: &str) {
    println!(
"Alias: {:?}!", alias);
}

fn print_name(name: &str) {
    println!(
"Name: {:?}!", name);
}

或者如果我们以后想再次使用person,我们可以克隆这些值:

#[derive(Debug)]
struct Person {
    name: String,
    alias: String,
}

fn main() {
    let person = Person { 
        name: "John".to_string(),
        alias:
"Johan".to_string(),
    };
    print_alias(person.alias.clone());
    print_name(person.name.clone());
    println!(
"{:?}", person);
}

fn print_alias(alias: String) {
    println!(
"Alias: {:?}!", alias);
}

fn print_name(name: String) {
    println!(
"Name: {:?}!", name);
}

或者你可以在不需要克隆的情况下移动东西。在这里,我们首先借用了Person,然后部分移动字段。

#[derive(Debug)]
struct Person {
    name: String,
    alias: String,
}

fn main() {
    let person = Person { 
        name: "John".to_string(),
        alias:
"Johan".to_string(),
    };
    println!(
"{:?}", person);
    print_alias(person.alias);
    print_name(person.name);
}

fn print_alias(alias: String) {
    println!(
"Alias: {:?}!", alias);
}

fn print_name(name: String) {
    println!(
"Name: {:?}!", name);
}