【问题标题】:Cannot borrow in a Rc as mutable不能在 Rc 中借用为可变的
【发布时间】:2019-10-28 23:14:27
【问题描述】:

首先我是 Rust 的新手 :-)

问题: 我想创建一个名为 RestServer 的模块,其中包含添加路由和启动服务器的方法 (actix-web)。

struct Route
{
   url: String,
   request: String,
   handler: Box<dyn Fn(HttpRequest) -> HttpResponse>
}


impl PartialEq for Route {
   fn eq(&self, other: &Self) -> bool {
     self.url == other.url
   }
}

impl Eq for Route {}

impl Hash for Route {
   fn hash<H: Hasher>(&self, hasher: &mut H) {
      self.url.hash(hasher);
   }
}

这是路由结构,这个结构包含路由 url、请求类型(GET、POST 等)和 hanlder 是必须捕获请求并返回 HTTPResponse 的函数

pub struct RestServer
{
   scopes: HashMap<String, Rc<HashSet<Route>>>,
   routes: HashSet<Route>,
   host: String,
}

impl RestServer {

   pub fn add_route(self, req: &str, funct: impl Fn(HttpRequest) -> HttpResponse + 'static,
                 route: &str, scope: Option<&str>) -> RestServer
   {
       let mut routes_end = self.routes;
       let mut scopes_end = self.scopes;
       let url = self.host;
       let route = Route {
          url: String::from(route),
          request: String::from(req),
          handler: Box::new(funct)
    };

    if let Some(x) = scope {
        if let Some(y) = scopes_end.get(x) {
            let mut cloned_y = Rc::clone(y);
            cloned_y.insert(route);
            scopes_end.insert(String::from(x), cloned_y);
        }else {
            let mut hash_scopes = HashSet::new();
            hash_scopes.insert(route);
            scopes_end.insert(String::from(x), Rc::new(hash_scopes));
        }
    } else {
        routes_end.insert(route);
    }

    RestServer {
        scopes: scopes_end,
        routes: routes_end,
        host: String::from(url)
    }
  }

最新的代码是RestServer的实现。 最重要的部分是 add_route 函数,该函数接收作为参数的路由字符串、函数处理程序、请求字符串和范围。 首先我创建路由对象。 我检查范围是否存在于 HashMap 中,如果是,我必须采用实际范围并更新 HashSet。

当我构建代码时,我得到以下错误

   error[E0596]: cannot borrow data in an `Rc` as mutable
   --> interface/src/rest/mod.rs:60:17
   |
60 |                 cloned_y.insert(route);
   |                 ^^^^^^^^ cannot borrow as mutable
   |
   = help: trait `DerefMut` is required to modify through a dereference, but it is not 
     implemented for `std::rc::Rc<std::collections::HashSet<rest::Route>>`

我知道编译器会给我一些帮助,但老实说,我不知道该怎么做,或者我是否可以用一些简单的解决方案来做。 在谷歌进行大量搜索后,我在 RefCell 中找到了一个解决方案,但不是很清楚

提前感谢您的帮助

【问题讨论】:

    标签: rust borrowing actix-web


    【解决方案1】:

    您不能将引用计数指针借用为可变的;这是因为它提供的保证之一只有在结构是只读的情况下才有可能。

    不过,您可以绕过它,但需要对签名进行一些更改。

    输入内部可变性

    内部可变性是您可能从其他编程语言中以互斥锁、原子和同步原语形式了解的概念。在实践中,这些结构允许您暂时保证您是给定变量的唯一访问者。

    在 Rust 中,这特别好,因为它允许我们从结构中提取对内部成员的可变引用,该结构只需要对自身的不可变引用才能运行。非常适合Rc

    根据您的需求,您会发现CellRefCell 结构正是您所需要的。这些不是线程安全的,但又一次,Rc 也不是,所以它不完全是一个交易破坏者。

    实际上,它的工作原理非常简单:

    let data = Rc::new(RefCell::new(true));
    {
      let mut reference = data.borrow_mut();
      *reference = false;
    }
    println!("{:?}", data);
    

    playground

    (如果您想要线程版本,Arc 替换 RcMutexRwLock 替换 Cell/RefCell

    【讨论】:

    • 非常感谢您的帮助,我将在接下来的几天内更新最多的解决方案:-)
    猜你喜欢
    • 1970-01-01
    • 2016-05-02
    • 1970-01-01
    • 2018-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-09-14
    相关资源
    最近更新 更多