rust Arc、Rc和Cell在web开发中使用到的场景

在web开发中常见的一场景:一个Person 实体有一个Vec<Address>的属性,

#[derive(Clone, Debug)]
struct Person {
    addrs: Vec<Address>
}

#[derive(Debug)]
struct Address {
  //person_id:String, 根据用户ID获取到所有地址
    name: String,
}

我们一般会有一个业务,获取所有Vec<Person>返回给用户,每个Person对象可以获取根据person_id获取到所有address。下面代码是套用其它语言的经验写的代码:

struct Person {
    id: String,
    name: String,
    address: Option<Vec<Address>>,
}

#[derive(Clone)]
struct Address {
    id: String,
    user_id: String,
    name: String,
}

fn main() {
    let persons = get_person_all();
    let address = get_address_all();

    for mut p in persons {
        let mut addrs = vec![];//会一直复制address中的数据
        for addr in &address {
            if p.id.eq(&addr.user_id) {
                addrs.push((*addr).clone());//会一直复制address中的数据
            }
        }
        p.address = Some(addrs);
    }
}

fn get_person_all() -> Vec<Person> {
    vec![Person { id: "id".into(), address: None, name: "rust".into() }]
}

fn get_address_all() -> Vec<Address> {
    vec![Address { id: "id".into(), user_id: "userid".into(), name: "address".into() }]
}

 上面会把Vec<Address>中的数据复制后放入person对象中。这样当数据量大时,确实会造成大量的内在复制。

用ARC改进后的代码:

use std::sync::Arc;
use std::thread;
use std::time::Duration;

fn main() {
    {
        create_data();
    }
    thread::sleep(Duration::from_secs(5));
}


fn create_data() {
    let address = vec![Address { name: "rust".into() }, Address { name: "golang".into() }, Address { name: "java".into() }];
    let address = address.into_iter().map(|addr| Arc::new(addr)).collect::<Vec<_>>(); ///在这里转化一下

    let mut persons = vec![];

    for i in 0..10 {

        let mut addrs = vec![];

        addrs.push(address[i % 3].clone());

        let p = Person { addrs };

        let clone_p=p.clone();

        persons.push(p);

        thread::spawn(move|| {
            thread::sleep(Duration::from_secs(2));
            println!("{:?}", clone_p)
        });
    }
}
#[derive(Clone, Debug)]
struct Person {
    addrs: Vec<Arc<Address>>//修改使用成ARC,因为会跨线程传递或clone所以用Arc
}

当时有想到使用RC或ARC,但觉得person中的属性addrs中的每个Address对象我有可能再更改,这样维护起来可能麻烦。后来在群里和大家讨论,又理了理,觉得Rc或Arc是可行的,就写了上面的demo验证了下。

而如果想修改addrs容器里的值,那么就配合cell或refcell和Mutex,看自己使用场景(深入浅出Rust这本书第15章节专门有介绍)。


#[derive(Clone, Debug)]
struct Person {
    addrs: Vec<Arc<Cell<Address>>>//这样就可以共享修改了
}

以上有问题,欢迎指正,这篇就是为了记录下使用rust中不套用其它语言经验,而需要用rust的方式来解决问题。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 7
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值