【问题标题】:How to have a struct that accepts closures calling methods from another variable? [duplicate]如何拥有一个接受来自另一个变量的闭包调用方法的结构? [复制]
【发布时间】:2026-01-26 14:20:02
【问题描述】:

所以我正在做这几年的代码出现,我遇到了一个借用问题:

如何拥有一个接受闭包调用另一个变量的方法的结构?这是我设法提出的一个最小示例。借用检查器不喜欢两个闭包都借用值。

如果我有一个围绕值的互斥体,那么它似乎可以工作,但我希望有一个更优雅的解决方案。

基本上,我希望拥有具有不同输入/输出功能的不同大脑,其中一个可能只是打印输出,另一个可能会将输出添加到 vec。

Playground link.

Actual code where I use it.

struct Brain<I, O>
where
    I: Fn() -> i32,
    O: FnMut(i32),
{
    input: I,
    output: O,
}

impl<I, O> Brain<I, O>
where
    I: Fn() -> i32,
    O: FnMut(i32),
{
    fn new(input: I, output: O) -> Self {
        Brain { input, output }
    }
}

fn runner() {
    let mut values = Vec::new();
    let request_input = || *values.last().unwrap();
    let add_output = |v| values.push(v);

    let _ = Brain::new(request_input, add_output);
}

【问题讨论】:

    标签: rust borrow-checker


    【解决方案1】:

    你做错了,你显然不能在 rust 中这样做,你只能有一个可变引用或一个和多个引用,但不能同时拥有。我建议您不要使用像 MutexCell 这样的内部可变性,而是使用 trait,例如,您可以这样做:

    trait Bus {
        fn input(&self) -> i32;
        fn output(&mut self, v: i32);
    }
    
    struct Brain<T>
    where
        T: Bus,
    {
        bus: T,
    }
    
    impl<T> Brain<T>
    where
        T: Bus,
    {
        fn new(bus: T) -> Self {
            Brain { bus }
        }
    }
    
    struct MyBus {
        values: Vec<i32>,
    }
    
    impl Bus for MyBus {
        fn input(&self) -> i32 {
            *self.values.last().unwrap()
        }
    
        fn output(&mut self, v: i32) {
            self.values.push(v)
        }
    }
    
    fn main() {
        let bus = MyBus { values: Vec::new() };
    
        let _ = Brain::new(bus);
    }
    

    这提供了很大的灵活性。

    【讨论】:

      最近更新 更多