> For the complete documentation index, see [llms.txt](https://chapin666.gitbook.io/too-many-list-zh/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://chapin666.gitbook.io/too-many-list-zh/yi-ge-hai-hang-de-dan-lian-zhan/intoiter.md).

# IntoIter

使用Iterator特性在Rust中对集合进行迭代。 它比Drop更复杂：

```rust
pub trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}
```

代码块内部有一个 type Item，这是在声明迭代器的每个实现都有一个名为 Item 的关联类型。在这种情况下，当您调用 next 方法时，它可以返回这种类型。

Iterator 返回 Option\<Self::Item> 的原因是该接口合并了 has\_next 和 get\_next 概念。 当拥有下一个值时，将返回 Some(value)，当没有下一个值时，将返回 None。 这使得 API 在使用和实现上更符合人体工程学，更安全，同时避免了冗余的检查和 has next 和 get next 之间的逻辑。 太棒了！

遗憾的是，Rust还没有一个像 yield 那样的东西（yet），因此我们将不得不自己实现逻辑。 此外，每个集合实际上应尝试实现3种不同的迭代器：

* IntoIter - `T`
* IterMut - `&mut T`
* Iter - `&T`

实际上，我们已经有了使用List接口实现 IntoIter 的所有工具：只需一遍又一遍地调用 pop。因此，我们只需要将 IntoIter 作为 List 的新型包装器实现：

```rust
// Tuple structs are an alternative form of struct,
// useful for trivial wrappers around other types.
pub struct IntoIter<T>(List<T>);

impl<T> List<T> {
    pub fn into_iter(self) -> IntoIter<T> {
        IntoIter(self)
    }
}

impl<T> Iterator for IntoIter<T> {
    type Item = T;
    fn next(&mut self) -> Option<Self::Item> {
        // access fields of a tuple struct numerically
        self.0.pop()
    }
}
```

让我们写一个测试：

```rust
#[test]
fn into_iter() {
    let mut list = List::new();
    list.push(1); list.push(2); list.push(3);

    let mut iter = list.into_iter();
    assert_eq!(iter.next(), Some(3));
    assert_eq!(iter.next(), Some(2));
    assert_eq!(iter.next(), Some(1));
    assert_eq!(iter.next(), None);
}
```

```rust
> cargo test

     Running target/debug/lists-5c71138492ad4b4a

running 4 tests
test first::test::basics ... ok
test second::test::basics ... ok
test second::test::into_iter ... ok
test second::test::peek ... ok

test result: ok. 4 passed; 0 failed; 0 ignored; 0 measured
```

太棒了！
