如何在成员方法闭包中使用struct self

2023-11-30

如何在闭包中调用方法?get_access_token方法可以基于设置新的访问令牌self.get_base_url():

fn fetch_access_token(_base_url: &String) -> String {
    String::new()
}

fn get_env_url() -> String {
    String::new()
}

pub struct App {
    pub base_url: Option<String>,
    pub access_token: Option<String>,
}

impl App {
    pub fn new() -> App {
        App {
            base_url: None,
            access_token: None,
        }
    }
    pub fn get_base_url(&mut self) -> &String {
        self.base_url.get_or_insert_with(|| get_env_url())
    }
    pub fn get_access_token(&mut self) -> &String {
        self.access_token
            .get_or_insert_with(|| fetch_access_token(self.get_base_url()))
    }
}

fn main() {}

error:

铁锈 2015

error[E0500]: closure requires unique access to `self` but `self.access_token` is already borrowed
  --> src/main.rs:26:33
   |
25 |         self.access_token
   |         ----------------- borrow occurs here
26 |             .get_or_insert_with(|| fetch_access_token(self.get_base_url()))
   |                                 ^^                    ---- borrow occurs due to use of `self` in closure
   |                                 |
   |                                 closure construction occurs here
27 |     }
   |     - borrow ends here

铁锈 2018

error[E0501]: cannot borrow `self.access_token` as mutable because previous closure requires unique access
  --> src/main.rs:25:9
   |
25 | /         self.access_token
26 | |             .get_or_insert_with(|| fetch_access_token(self.get_base_url()))
   | |______________------------------_--____________________----________________^ second borrow occurs here
   |                |                  |                     |
   |                |                  |                     first borrow occurs due to use of `self` in closure
   |                |                  closure construction occurs here
   |                first borrow later used by call

error[E0500]: closure requires unique access to `self` but it is already borrowed
  --> src/main.rs:26:33
   |
24 |       pub fn get_access_token(&mut self) -> &String {
   |                               - let's call the lifetime of this reference `'1`
25 |           self.access_token
   |           -----------------
   |           |
   |  _________borrow occurs here
   | |
26 | |             .get_or_insert_with(|| fetch_access_token(self.get_base_url()))
   | |_________________________________^^____________________----________________- returning this value requires that `self.access_token` is borrowed for `'1`
   |                                   |                     |
   |                                   |                     second borrow occurs due to use of `self` in closure
   |                                   closure construction occurs here

将您的数据和方法拆分为更小的组件,然后您可以对各种组件进行不相交的借用self:

fn fetch_access_token(_base_url: &str) -> String { String::new() }
fn get_env_url() -> String { String::new() }

#[derive(Default)]
struct BaseUrl(Option<String>);

impl BaseUrl {
    fn get(&mut self) -> &str {
        self.0.get_or_insert_with(|| get_env_url())
    }
}

#[derive(Default)]
struct App {
    base_url: BaseUrl,
    access_token: Option<String>,
}

impl App {
    fn new() -> App {
        App::default()
    }

    fn get_access_token(&mut self) -> &str {
        let base_url = &mut self.base_url;
        self.access_token
            .get_or_insert_with(|| fetch_access_token(base_url.get()))
    }
}

fn main() {}

您可以更进一步,对这两个值执行此操作:

fn fetch_access_token(_base_url: &str) -> String { String::new() }
fn get_env_url() -> String { String::new() }

#[derive(Default)]
struct BaseUrl(Option<String>);

impl BaseUrl {
    fn get(&mut self) -> &str {
        self.0.get_or_insert_with(|| get_env_url())
    }
}

#[derive(Default)]
struct AccessToken(Option<String>);

impl AccessToken {
    fn get(&mut self, base_url: &str) -> &str {
        self.0.get_or_insert_with(|| fetch_access_token(base_url))
    }
}

#[derive(Default)]
struct App {
    base_url: BaseUrl,
    access_token: AccessToken,
}

impl App {
    fn new() -> App {
        App::default()
    }

    fn get_access_token(&mut self) -> &str {
        let base_url = self.base_url.get();
        self.access_token.get(base_url)
    }
}

fn main() {}

这让您看到可以抽象出常见的功能:

fn fetch_access_token(_base_url: &str) -> String { String::new() }
fn get_env_url() -> String { String::new() }

#[derive(Default)]
struct StringCache(Option<String>);

impl StringCache {
    fn get<F>(&mut self, f: F) -> &str
    where
        F: FnOnce() -> String,
    {
        self.0.get_or_insert_with(f)
    }
}

#[derive(Default)]
struct App {
    base_url: StringCache,
    access_token: StringCache,
}

impl App {
    fn new() -> App {
        App::default()
    }

    fn get_access_token(&mut self) -> &str {
        let base_url = self.base_url.get(get_env_url);
        self.access_token.get(|| fetch_access_token(base_url))
    }
}

fn main() {}

然后你意识到抽象可以变得通用:

fn fetch_access_token(_base_url: &str) -> String { String::new() }
fn get_env_url() -> String { String::new() }

#[derive(Default)]
struct Cache<T>(Option<T>);

impl<T> Cache<T> {
    fn get<F>(&mut self, f: F) -> &T
    where
        F: FnOnce() -> T,
    {
        self.0.get_or_insert_with(f)
    }
}

#[derive(Default)]
struct App {
    base_url: Cache<String>,
    access_token: Cache<String>,
}

impl App {
    fn new() -> App {
        App::default()
    }

    fn get_access_token(&mut self) -> &str {
        let base_url = self.base_url.get(get_env_url);
        self.access_token.get(|| fetch_access_token(base_url))
    }
}

fn main() {}

也可以看看:

  • 借用对结构体中属性的引用
  • Rust 编程语言关于闭包的章节,它创建这个缓存​​结构作为练习的一部分。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

如何在成员方法闭包中使用struct self 的相关文章

随机推荐

  • Python:创建带有前缀的顺序列表的简短方法

    如何生成如下字符串 或 Pandas 系列 a1 a2 a3 a4 a19 以下有效 但我想知道更短的方法 my str for i in range 1 20 comma if i 19 else my str d str i comma
  • AES 加密,解密文件中出现额外的垃圾字符

    我正在 Android 应用程序中制作调试日志记录功能 我有一个简单的课程是使用 128 位 AES 加密记录到 txt 文件 日志记录完成后 我用一个简单的JAVA程序解密记录的文件 问题是当我解密加密日志时我里面有一些奇怪的内容我也得到
  • 如何在 Zapier CLI 中使用 post_poll 方法

    根据docs 我应该使用post poll添加缺失的功能id响应中的字段 如何添加 post poll 函数 这是我的错误 结果必须是一个数组 得到 对象 totalevents 83 events eventid 10266033 c 得
  • 使用 spring-mongo 关闭 mongo 连接的正确方法是什么?

    我在我的网络应用程序中使用 spring mongo 当我在 Tomcat7 中取消部署应用程序时 出现内存泄漏 我怀疑可能是我没有明确关闭的 Mongo 对象 我想知道关闭它的正确方法 和位置 是什么 像这样的事情怎么样 Componen
  • 使用 v1 linkedin 公司共享 api 的 HTTP 500 响应

    尝试通过 LinkedIn API 为特定公司页面发布内容失败已过去 2 天 并显示 内部服务错误 奇怪的是 它只发生在这个特定的公司页面 id 10684715 而不是我们发布到的任何其他公司页面 代码在php ini中 我检查了公司页面
  • 防止
     包裹在表格内                
                

    我有一个有两列的表 一个有一些属性名称 另一个有描述 包括预标记 我需要预标记不换行 而是滚动以查看溢出 我还需要根据最大的属性名称调整第一列的大小 我无法让两个人好好相处 例如 我可以根据内容调整第一列的大小 但 pre 不会滚动 mai
  • 粒子.js没有出现在reactjs项目中

    我最近了解了 Particle js 并想在我的 Reactjs 应用程序中使用它 我使用下面提到的命令安装了它 npm install react particles js 并且安装成功了 我在node modules文件夹中检查了它 发
  • CSP 随机数实现是什么样的?

    我最近一直在阅读 CSP 的内容 但我未能找到关于 nonce 如何工作的清晰解释或可靠示例 我试图避免使用unsafe inline出于安全考虑 到目前为止 我的理解如下 服务器每次连接都会生成一个新的随机数 客户端通过以下方式获取此随机
  • 画出带频率的正弦波?

    我正在绘制正弦波的一个周期 let width rect width let height rect height let origin CGPoint x width 1 graphWidth 2 y height 0 50 let pa
  • python正则表达式用于重复字符串

    我想验证然后解析这个字符串 用引号引起来 string start c12354 c3456 34526 other stuff that I don t care about Note that some codes begin with
  • 用负前瞻反应路由器

    基本上我想抓住
  • 如何在Java中调试“java.lang.NumberFormatException:对于输入字符串:X”?

    我正在尝试运行一个程序 我对 Java 真的很陌生 当我运行我的程序时 出现以下异常 Description The server encountered an internal error that prevented it from f
  • Google App脚本:您没有权限调用提示

    我创建了一个谷歌脚本 在编辑列时向我显示一个提示对话框以撰写评论 由于某种原因 这仅适用于我的电子邮件 脚本的创建者 但对我共享电子表格的其他用户不起作用 当我使用其他用户帐户打开脚本编辑器时 我可以在查看 gt 执行脚本 执行失败 您没有
  • 如何在 Piston 类方法中访问 request.user

    我有一个模型 其中包含一个 ManyToMany to User 来跟踪哪些用户 最喜欢 特定的模型实例 在此模型的 API 中 当经过身份验证的用户请求时 我想包含一个 is favorite 布尔值 然而 似乎任何不是直接模型属性的 a
  • C# 中 x+=y 和 x=x+y(x 和 y 都是简单类型)之间有性能差异吗? [复制]

    这个问题在这里已经有答案了 在 C C 中 复合赋值运算符将简单赋值运算符与另一个二元运算符组合起来 复合赋值运算符执行附加运算符指定的运算 然后将结果赋给左侧操作数 例如 复合赋值表达式如 expression1 expression2
  • float 多线图动画

    我在图表上有多个系列 想为它们设置动画 但它不起作用 我正在使用 flot 和 animator 插件 https jsfiddle net shorif2000 L0vtrgc2 var datasets label IT curvedL
  • 将配置文件添加到安装程序 (msi)

    如何将带有特殊的唯一生成令牌的配置文件添加到 msi 文件中 这个想法是 用户注册客户端计算机 安装程序在配置文件中提供唯一值 我读过有关 msidb exe 的内容 但我想知道是否有更好 更干净 更简单的解决方案 有任何想法吗 添加自定义
  • 使用固定大小的可拖动图片框裁剪图像

    我正在开发一个涉及裁剪图像的 winforms 项目 我的目标是通过使用固定大小的可拖动图片框控件来实现此目的 允许用户选择他们想要保留的区域 我的问题是当我裁剪图像时 它 works 但裁剪面积略有偏移 这是我得到的结果 需要澄清的是 我
  • 从代码创建材质并将其分配给对象

    我对 Unity3d 很陌生 我有一个预制件 其中包含 6 个四边形 使其成为一个立方体 我想将图像纹理添加到立方体的不同面 我从网络服务获取图像 因此我必须在脚本中添加或更改材料 我面临的问题是 我无法在游戏对象中找到材质属性 我试过下面
  • 如何在成员方法闭包中使用struct self

    如何在闭包中调用方法 get access token方法可以基于设置新的访问令牌self get base url fn fetch access token base url String gt String String new fn