我对 rust 病很陌生,我的一生都有一个问题,我相信我能理解正在发生的事情和原因,但我无法在头脑中思考如何解决它.

为了简单起见,我创建了这个简短的"克隆"我实际上试图做的事情,但真正的代码是使用asyc-stripe.将用真实代码注释示例代码,以防相关.

struct 如下:

// https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/resources/generated/subscription.rs#L385
struct ObjectA<'a> {
    field: i32,
    object_b_id: Option<&'a str>,
}

// https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/resources/generated/subscription.rs#L570
impl<'a> ObjectA<'a> {
    fn new(field: i32) -> Self {
        return Self {
            field,
            object_b_id: Default::default(),
        };
    }
}

// https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/resources/generated/subscription.rs#L210
fn persist_obj_a(obj_a: ObjectA<'_>) {}

// ---

// https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/resources/generated/payment_method.rs#L18
struct ObjectB {
    id: ObjectBId,
}

// https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/ids.rs#L518
struct ObjectBId {
    value: String,
}

impl ObjectBId {
    fn as_str(&self) -> &str {
        return self.value.as_str();
    }
}

// This is a wrapper around https://github.com/arlyon/async-stripe/blob/9f1a84144a23cc7b2124a1252ee15dc646ce0215/src/resources/generated/payment_method.rs#L128 that just returns the first one found (id any, hence the Option)
fn load_object_b() -> Option<ObjectB> {
    return Some(ObjectB {
        id: ObjectBId {
            value: String::from("some_id"),
        },
    });
}

我想做的是:用load_object_b加载ObjectB,然后用它的ID输入ObjectA.

好的,接下来是我的try .

第一次try

fn first_try(condition: bool) {
    let mut obj_a = ObjectA::new(1);

    if condition {
        match load_object_b() {
            Some(obj_b) => obj_a.object_b_id = Some(obj_b.id.as_str()),
            None => (),
        }
    }

    persist_obj_a(obj_a);
}

我在这里

obj_b.id岁还不够长寿

我能理解,因为据我所知,obj_b只存在于比赛期间,并且在比赛结束时就消失了.

第二次try

fn second_try(condition: bool) {
    let mut obj_a = ObjectA::new(1);

    if condition {
        let obj_b = load_object_b();
        match obj_b {
            Some(ref obj_b) => obj_a.object_b_id = Some(obj_b.id.as_str()),
            None => (),
        }
    }

    persist_obj_a(obj_a);
}

我明白了

obj_b.0岁还不够长寿

我猜这仍然是相同的 idea ,只是在不同的地方.根据我的理解,现在obj_b只生活在if条件的范围内.

第三次也是最后一次try

我最终用以下方法"解决"了它:

fn third_try(condition: bool) {
    let mut obj_a = ObjectA::new(1);

    let obj_b = load_object_b();
    let obj_b_id = match obj_b {
        Some(ref obj_b) => Some(obj_b.id.as_str()),
        None => None,
    };

    if condition {
        obj_a.object_b_id = obj_b_id;
    }

    persist_obj_a(obj_a);
}

在这里,我移动了obj_b,使其生命周期 与obj_a相同.所以它解决了我遇到的问题.

推荐答案

我认为这应该行得通:

fn third_try(condition: bool) {
    let mut obj_a = ObjectA::new(1);

    let obj_b = if condition { load_object_b() } else { None };
    obj_a.object_b_id = obj_b.as_ref().map (|o| o.id.as_str());

    persist_obj_a(obj_a);
}

Rust相关问答推荐

将大小为零的类型实例存储到空指针中

在自身功能上实现类似移动的行为,以允许通过大小的所有者进行呼叫(&;mut;self)?

返回的future 不是`发送`

限制未使用的泛型导致编译错误

什么时候和为什么S最好是按值或引用传递简单类型

正则表达式中的重叠匹配?(铁 rust 正则式发动机)

如何使用Actix Web for Rust高效地为大文件服务

是否可以使用Serde/Rust全局处理无效的JSON值?

处理带有panic 的 Err 时,匹配臂具有不兼容的类型

Rust 如何将链表推到前面?

Sized问题的动态调度迭代器Rust

`tokio::pin` 如何改变变量的类型?

如何限制通用 const 参数中允许的值?

使用 traits 时,borrow 的值不会存在足够长的时间

字符串切片的向量超出范围但原始字符串仍然存在,为什么判断器说有错误?

Rust HRTB 是相同的,但编译器说一种类型比另一种更通用

有没有办法隐藏类型定义?

在使用大型表达式时(8k 行需要一小时编译),是否可以避免 Rust 中的二次编译时间?

HashMap entry() 方法使borrow 的时间比预期的长

为什么当borrow 变量发生变化时,borrow 变量不会改变?