Let‘s Go Rust 系列之for对比

本文对比分析了Rust和Golang中的遍历机制,包括数组、切片、Map的遍历方式,以及并发任务分发中的陷阱。在Golang中,for range可能导致数据竞态条件,而在Rust中,所有权和生命周期机制避免了此类问题。文章还讨论了如何在遍历过程中修改数据以及使用Arc优化并发操作。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言
在golang中提供了for range 语法糖帮助我们方便的遍历数据或切片,也可以遍历map和channel;在rust中则提供了 for in 语法糖帮助我们方便的遍历Array,Vector或切片,也可以遍历map。本文将会通过多种类型的例子介绍两种语言中这些语法糖背后的机制以及使用不当可能遇到的陷阱。

遍历方式对比

Golang

我们先来看Golang中的三种遍历方式:

arr := []int{
   2, 4, 6}

    // 只要索引
    for i := range arr {
   
        fmt.Println(i)
    }

    // 索引和数值
    for i, v := range arr {
   
        fmt.Println(i, v)
    }

    // 只要数值
    for _, v := range arr {
   
        fmt.Println(v)
    }

输出

0
1
2
0 2
1 4
2 6
2
4
6

Rust

首先我们要了解在rust中遍历arr有下面四种不同的方法,本质都是将当前arr转为了相应的iterator。

let arr = vec![1, 2, 3];
    for a in arr {
   
        println!("{}", a);
    }

    let arr = vec![1, 2, 3];
    for a in arr.into_iter() {
   
        println!("{}", a);
    }

    let arr = vec![1, 2, 3];
    for a in arr.iter() {
   
        println!("{}", a);
    }

    let mut arr = vec![1, 2, 3];
    for a in arr.iter_mut() {
   
        println!("{}", a);
    }

其中 for a in arr 等价于for a in arr.into_iter() ,这种遍历方式会把当前arr中的变量 move 掉,执行遍历后,arr无法再使用。

for a in arr.iter() 返回arr中每一项的不可变借用,for a in arr.iter_mut() 返回arr中每一项的可变借用,遍历后arr可以继续使用。

如果还需要索引,那么就要使用iterator的enumerate方法,这个方法将当前迭代器封装成迭代元素是包含索引和元素的元组的迭代器,如下:

let arr = vec![1, 2, 3];
    for (i, v) in arr.into_iter().enumerate() {
   
        println!("{} {}", i, v);
    }

    let arr = vec![1, 2, 3];
    for (i, v) in arr.iter().enumerate() {
   
        println!("{} {}", i, v);
    }

    let mut arr = vec![1, 2, 3];
    for (i, v) in arr.iter_mut().enumerate() {
   
        println!("{} {}", i, v);
    }

在Rust中还有一个常用的只返回索引的遍历方法:

for i in 1..4{
   
        println!("{}",i);
    }

输出:

1
2
3

可以看到 beg..end 是一个左闭右开的区间,不包含end。

并发任务分发

在实际项目开发中,经常会需要将一组任务数据分发给不同的goroutine或thread来并发执行。

Golang

我们先来看在Golang中常见的错误写法

func slice_trap_wrong() {
   

    in := []int{
   1, 2, 3}
    for _, b := range in {
   
        go func() {
   
            fmt.Println("job", b)
        }()
    }

}

func main() {
   

    slice_trap_wrong()
    select {
   
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值