# Let's Go Rust 系列之for对比

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

``````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.iter()` 返回arr中每一项的不可变借用，`for a in arr.iter_mut()` 返回arr中每一项的可变借用，遍历后arr可以继续使用。

``````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);
}``````

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

1
2
3

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 {}

}``````

``````job 3
job 3
job 3
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [select (no cases)]:
main.main()
/home/repl/904b2209-3e69-479f-a530-1954e1cf59cd/main.go:25 +0x25
exit status 2

** Process exited - Return Code: 1 **``````

1. 将任务数据作为入参传入，因为golang中参数传递都是按值传递的，所以进入到goroutine中的b已经是复制之后的一个新的变量

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

2.在传入goroutine的闭包之前手动进行一次复制

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

Rust

``````let arr = vec![1, 2, 3];
let mut t_arr = vec![];
for a in arr {
t_arr.push(thread::spawn(|| println!("{}", a)));
}

// 等待所有线程执行结束
for t in t_arr {
t.join().unwrap();
}``````

``````error[E0373]: closure may outlive the current function, but it borrows `a`, which is owned by the current function
--> src/main.rs:16:34
|
16 |         t_arr.push(thread::spawn(|| println!("{}", a)));
|                                  ^^                - `a` is borrowed here
|                                  |
|                                  may outlive borrowed value `a`
|
note: function requires argument type to outlive `'static`
--> src/main.rs:16:20
|
16 |         t_arr.push(thread::spawn(|| println!("{}", a)));
|                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
help: to force the closure to take ownership of `a` (and any other referenced variables), use the `move` keyword
|
16 |         t_arr.push(thread::spawn(move || println!("{}", a)));
|                                  ++++

For more information about this error, try `rustc --explain E0373`.
error: could not compile `channel` due to previous error``````

Rust错误提示中给出了解决方法，使用move关键字，让闭包获取a的所有权：

``````let arr = vec![1, 2, 3];
let mut t_arr = vec![];
for a in arr {
println!("{:p}", &a);
t_arr.push(thread::spawn(move || println!("{} {:p}", a, &a)));
}

for t in t_arr {
t.join();
}
``````

``````0x7ffe3a4398d4
0x7ffe3a4398d4
1 0x7f68b4b87b8c
0x7ffe3a4398d4
2 0x7f68b4986b8c
3 0x7f68b4785b8c``````

``````let arr = vec![1, 2, 3];
let mut t_arr = vec![];
for a in arr.iter(){
println!("{:p}",a);
}
for a in arr {
println!("{:p}", &a);
t_arr.push(thread::spawn(move || println!("{} {:p}", a, &a)));
}

for t in t_arr {
t.join();
}``````

``````0x5633d313ead0
0x5633d313ead4
0x5633d313ead8
0x7ffdbb7d2cc4
0x7ffdbb7d2cc4
1 0x7fee6d482b8c
0x7ffdbb7d2cc4
2 0x7fee6d281b8c
3 0x7fee6d080b8c``````

`pub struct People {

``pub age: i32,``

}`

``````let arr = vec![People { age: 1 }, People { age: 2 }, People { age: 3 }];
let mut t_arr = vec![];
for a in arr.iter() {
println!("{:p}", a);
}
for a in arr {
println!("{:p}", &a);
t_arr.push(thread::spawn(move || println!("{} {:p}", a.age, &a)));
}

for t in t_arr {
t.join();
}``````

``````0x555c64ec9ad0
0x555c64ec9ad4
0x555c64ec9ad8
0x7ffdc5766474
0x7ffdc5766474
1 0x7f0b6f4b1b8c
0x7ffdc5766474
2 0x7f0b6f2b0b8c
3 0x7f0b6f0afb8c``````

Arc优化

Arc 是一种线程安全的引用计数指针，可以安全的在线程之前传递。

``````let arr = vec![
Arc::new(People { age: 1 }),
Arc::new(People { age: 2 }),
Arc::new(People { age: 3 }),
];
let mut t_arr = vec![];
for a in arr.iter() {
// 执行复制，实际只是增加了strong引用计数
let a = Arc::clone(a);
t_arr.push(thread::spawn(move || {
// 通过 Arc::strong_count 可以得到Arc中的strong引用计数
println!("in thread {} count:{}", a.age, Arc::strong_count(&a))
}));
}

for t in t_arr {
t.join().unwrap();
}

// 线程执行结束后，内部的a被drop掉，实际只是减少了strong引用计数
for a in arr {
println!("final: {} count:{}", a.age, Arc::strong_count(&a));
}``````

in thread 1 count:2
in thread 3 count:2
in thread 2 count:2
final: 1 count:1
final: 2 count:1
final: 3 count:1

Golang

``````func main() {
arr := []int{1, 2, 3}
for _, v := range arr {
arr = append(arr, v)
}
fmt.Println(arr)
}

\$ go run main.go
1 2 3 1 2 3``````

Rust

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

rust报错，由于rust的所有权安全机制，同时只能有一个mut的借用，并且此时也不能有其它的只读借用。

``````error[E0502]: cannot borrow `arr` as mutable because it is also borrowed as immutable
--> src/main.rs:41:9
|
39 |     for a in arr.iter() {
|              ----------
|              |
|              immutable borrow occurs here
|              immutable borrow later used here
40 |         println!("{}", a);
41 |         arr.push(4);
|         ^^^^^^^^^^^ mutable borrow occurs here``````

``````let mut arr = vec![1, 2, 3];
let mut i = 0;
let len = arr.len();
while i < len {
arr.push(arr[i]);
i += 1;
}``````

``````let mut arr = vec![1, 2, 3];
let mut i = 0;
while i < arr.len() {
arr.push(arr[i]);
i += 1;
}``````

Golang
Golang例子同样来自于 Go 语言for 和 range 实现

``````func main() {
arr := []int{1, 2, 3}
newArr := []*int{}
for _, v := range arr {
newArr = append(newArr, &v)
}
for _, v := range newArr {
fmt.Println(*v)
}
}

\$ go run main.go
3 3 3``````

``for i:=0;i``
``` 实际上是 v:=0 for i:=0;i 详细的可以去看原文以及下面的评论，大家也可以把arr中和newArr中的遍历的地址打印出来就明白了。 Rust我们使用 for a in arr.iter() 直接获取arr中每一个遍历的不可变借用，所以程序中new_arr可以按照预期正常打印 let arr: Vec = vec![1, 2, 3]; let mut new_arr: Vec<&i32> = vec![]; for a in arr.iter() { new_arr.push(a); } for a in new_arr { println!("{}", *a); } 输出123 需要注意的是，如果使用下面的方式编写，会编译报错 let arr: Vec = vec![1, 2, 3]; let mut new_arr: Vec<&i32> = vec![]; for a in arr { new_arr.push(&a); } for a in new_arr { println!("{}", *a); } 原因在于for a in arr 执行结束后，a就被drop掉了，这里的a的声明周期不足以支撑到 for a in new_arr: error[E0597]: `a` does not live long enough --> src/main.rs:60:22 | 60 | new_arr.push(&a); | ^^ borrowed value does not live long enough 61 | } | - `a` dropped here while still borrowed 62 | for a in new_arr { | ------- borrow later used here 另外我们可以再做个测试样例看for a in arr中的a是不是在每次迭代中创建了一个新变量还是复用一个变量： let arr: Vec = vec![1, 2, 3]; for a in arr.iter(){ println!("{:p}",a); } for a in arr { println!("{:p}",&a); } 我们首先通过 arr.iter()得到arr中每个元素的不变借用，也就是元素地址打印出来，然后再把 for a in arr 中的每次迭代中的a的地址打印出来，如下： 0x563932220b10 0x563932220b14 0x563932220b18 0x7fff5e40c2e4 0x7fff5e40c2e4 0x7fff5e40c2e4 for a in arr中的打印看到地址都一样，说明复用了同一个变量，跟golang中的 for range 类似。 遍历 map这里简单对比下两种语言的遍历方式，更加详细的map的对比会有专门一期文章来讲。 Golang scores := make(map[string]int) scores["Yello"] = 50 scores["Blue"] = 10 for k, v := range scores { fmt.Println(k, v) } Rust use std::collections::HashMap; let mut scores = HashMap::new(); scores.insert(String::from("Blue"), 10); scores.insert(String::from("Yellow"), 50); for (key, value) in &scores { println!("{}: {}", key, value); } 参考 Go 语言for 和 range 实现 https://draveness.me/golang/d... ```
``` ```
``` ```
``` ```
``` ```
``` ```
``` ```
``` ```
``` 你可能感兴趣的 Java 并发包之线程池和原子计数 lijingyao8206 Java计数ThreadPool并发包java线程池 java编程思想 抽象类和接口 百合不是茶 java抽象类接口 [房地产与大数据]房地产数据挖掘系统 comsci 数据挖掘 数组队列总结 沐刃青蛟 数组队列 Oracle存储过程无法编译的解决方法 IT独行者 oracle存储过程　 重装系统之后oracle恢复 文强chu oracle python学习二（ 一些基础语法） 小桔子 pthon基础语法 svn 常用命令 aichenglong SVN版本回退 按字母分类： ABCDEFGHIJKLMNOPQRSTUVWXYZ其他 首页 - 关于我们 - 站内搜索 - Sitemap - 侵权投诉 版权所有 IT知识库 CopyRight © 2000-2050 IT知识库 IT610.com , All Rights Reserved. 京ICP备09083238号 ```