我有一个入口点,其中ctx由父级传递:
pub mod instructions;
#[program]
pub mod solana_anchor_coinflip {
use super::*;
pub fn flip(ctx: Context<Play>, data: FlipArgs) -> Result<()> {
instructions::play::play(ctx, data)
}
}然后,instructions/play.rs有以下内容:
pub fn play(ctx: Context<Play>, data: FlipArgs) -> Result<()> {
ctx.accounts.game.flip(ctx, data) // <== cannot move out of `ctx` because it is borrowed
}
#[derive(Accounts)]
pub struct Play<'info> {
#[account(mut)]
pub game: Account<'info, Game>,
pub player: Signer<'info>,
}ctx最终被传递给game.rs
impl Game {
pub fn flip(&mut self, ctx: Context<Play>, data: FlipArgs) -> Result<()> {
self.charge_fee(ctx);
match data.heads_or_tails {
true => self.play_heads(ctx), // <== use of moved value: `ctx`
false => self.play_tails(ctx),
}
}
fn charge_fee(&self, ctx: Context<Play>) -> Result<()> {
let player = &ctx.accounts.player;
// ...
Ok(())
}
}如何从ctx中正确借用lib.rs > play.rs > game.rs
发布于 2022-04-22 08:13:56
正如在评论中所说的,你不是在借用ctx,你只是在移动它。请参阅相关文件以了解差异,并与示例一起说明这一点。
如果你仔细阅读,你就会明白为什么你只需要改变你的函数的签名:
// in instructions/play.rs
pub fn play(ctx: &Context<Play>, data: FlipArgs) -> Result<()> { // <-- takes a `&Context<Play>`
ctx.accounts.game.flip(ctx, data) // and passes the borrow
}
// game.rs
impl Game {
pub fn flip(&mut self, ctx: &Context<Play>, data: FlipArgs) -> Result<()> { // <-- takes a &Context<Play>
self.charge_fee(ctx); // <-- here you pass the borrow
// also, unused `Result`, which is _bad_
if data.heads_or_tails { // an `if` statement is a `match` over a `bool`
self.play_heads(ctx) // <-- here you pass the borrow too, which is fine, because `&T: Copy`
} else {
self.play_tails(ctx) // <-- same as above
}
}
fn charge_fee(&self, ctx: &Context<Play>) -> Result<()> { // <-- takes a `&Context<Play>`
let player = &ctx.accounts.player;
// ...
Ok(())
}
}但是,尽管有此修补程序,出于多种动机,您还是需要在理解了“借”之后重构代码:
play是向Context<Play>借款,还是向拥有的值借款,因为两者都可以工作(在第二种情况下,您必须将借款传递给方法调用,即ctx.accounts.game.flip(&ctx, data) )。data作为一个拥有的值传递,就像您对ctx所做的一样,但是由于这是ctx的一个错误,它可能也适用于data (以及您的代码的许多其他部分)。flip的&mut self,也就是说,它需要在play函数中向ctx.accounts.game进行可变的借用。但是,这也需要ctx的可变借用(除非是它不会,但这有点太高级了:在调用期间先了解借款,再学习内部可变性),这将使任何要作为参数传递的借款无效。作为建议,我建议您在设计复杂应用程序的体系结构之前,先了解Rust的核心概念(通过阅读锈书可以有效地完成),因为Rust有一些非常特殊的模式,即使使用其他编程语言也是如此。否则,当您仍然不完全理解Rust中的借用和所有权时,您将继续与编译器斗争,试图修改您所想到的代码,以适应一些有用的东西。
https://stackoverflow.com/questions/71964033
复制相似问题