欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

一文帶大家搞懂Go語言中的迭代器

 更新時(shí)間:2025年02月10日 08:58:11   作者:木卯  
迭代器是使用戶可在容器對象上遍訪的對象,設(shè)計(jì)人員使用此接口無需關(guān)心容器對象的內(nèi)存分配的實(shí)現(xiàn)細(xì)節(jié),本文主要為大家詳細(xì)介紹一下Go語言中的迭代器的實(shí)現(xiàn),需要的可以了解下

1. 迭代器簡介

1.1 定義

維基百科上迭代器的定義:迭代器(英語:iterator),是使用戶可在容器對象(container,例如鏈表或數(shù)組)上遍訪的對象,設(shè)計(jì)人員使用此接口無需關(guān)心容器對象的內(nèi)存分配的實(shí)現(xiàn)細(xì)節(jié)。

1.2 為何需要迭代器

理論上,迭代器的功能可以通過其他方法實(shí)現(xiàn),那為何還需要迭代器呢?迭代器之所以存在,自然是有它的優(yōu)點(diǎn)的:

  • 節(jié)省內(nèi)存: 迭代器不會一次性將所有數(shù)據(jù)都加載到內(nèi)存中,而是按需生成數(shù)據(jù)。比如在逐行讀取大文件時(shí)使用迭代器能顯著減少內(nèi)存的使用。
  • 性能優(yōu)化:迭代器僅在需要時(shí)生成數(shù)據(jù),可以減少不必要的計(jì)算。比如,數(shù)據(jù)庫查詢結(jié)果集逐行返回,而不是一次性返回所有記錄。
  • 解耦數(shù)據(jù)生成邏輯與遍歷邏輯:迭代器負(fù)責(zé)生成數(shù)據(jù),其邏輯是獨(dú)立的,不受遍歷數(shù)據(jù)邏輯的影響。同樣的 ,遍歷迭代器時(shí)無需考慮數(shù)據(jù)生成的細(xì)節(jié)。

2. Go 1.23版本之前的迭代器

在 1.23 版本之前,Go 官方是沒有提供傳統(tǒng)意義上的迭代器的,如果要用到迭代器的功能,就需要自己實(shí)現(xiàn)。下面來說說兩種比較有代表性的實(shí)現(xiàn)。

面向?qū)ο笳Z言的迭代器

在面向?qū)ο笳Z言中,Java 中的 Iterator 迭代器是比較有代表性的,下面使用 Go 來實(shí)現(xiàn)一個(gè)類似的迭代器。

package main  
  
import "fmt"  
  
type Iterator struct {  
    data  []int  
    index int  
}  
  
func NewIterator(data []int) *Iterator {  
    return &Iterator{data: data, index: 0}  
}  
  
func (it *Iterator) HasNext() bool {  
    return it.index < len(it.data)  
}  
  
func (it *Iterator) Next() int {  
    if it.index >= len(it.data) {  
       panic("沒有元素了")  
    }  
    item := it.data[it.index]  
    it.index++  
    return item  
}  
  
func main() {  
    it := NewIterator([]int{1, 2, 3, 4, 5})  
    for it.HasNext() {  
       fmt.Println(it.Next())  
    }  
}

這種面向?qū)ο髮?shí)現(xiàn)的迭代器不夠簡潔,一般而言,在實(shí)際編程中很少自定義這樣的迭代器。

函數(shù)形式的迭代器

Go 中使用函數(shù)形式實(shí)現(xiàn)的迭代器,比較有代表性的是使用協(xié)程和通道來實(shí)現(xiàn)的:

package main  
  
import "fmt"  
  
func generator(num int) <-chan int {  
    ch := make(chan int)  
    go func() {  
       for i := 0; i < num; i++ {  
          ch <- i  
       }  
       close(ch)  
    }()  
    return ch  
}  
  
func main() {  
    for n := range generator(5) {  
       fmt.Println(n)  
    }  
}

這種形式的迭代器,相對面向?qū)ο蟮牡饕啙嵉枚唷2贿^該方式使用了協(xié)程來實(shí)現(xiàn),其性能要差很多。

3. Go 1.23版本的迭代器

Go 1.23 版本提供了一個(gè) iter 包,算是 Go 官方提供了一個(gè)標(biāo)準(zhǔn)的迭代器實(shí)現(xiàn)。

Go 1.23 的迭代器是一個(gè)函數(shù)類型,把另一個(gè)函數(shù)( yield 函數(shù))作為參數(shù),定義迭代器時(shí)將元素傳遞給 yield 函數(shù)。迭代器函數(shù)會在以下兩種情況停止。

  • 在序列迭代結(jié)束后停止,表示此次迭代結(jié)束。
  • 在 yield 函數(shù)返回 false 時(shí)停止,表示提前停止迭代。

下面使用 iter 包來實(shí)現(xiàn)函數(shù)形式的迭代器,iter.Seq[V any]func(yield func(V) bool) 的簡稱:

package main  
  
import (  
    "fmt"  
    "iter")  
  
func generator(num int) iter.Seq[int] {  
    return func(yield func(int) bool) {  
       for i := 0; i < num; i++ {  
          if !yield(i) {  
             return  
          }  
       }  
    }  
}  
  
func main() {  
    for n := range generator(5) {  
       fmt.Println(n)  
    }  
}

這種形式的迭代器,兼顧了性能和簡潔性。

在性能方面,筆者測試了一下,使用 yield函數(shù) 實(shí)現(xiàn)的迭代器,比使用協(xié)程和通道實(shí)現(xiàn)的迭代器,提升了 200 多倍的性能!

簡潔性是相對面向?qū)ο髞碚f的。有些遺憾的是,相比其他的一些語言,上面的實(shí)現(xiàn)在簡潔明了方面做得不夠好。generator 需要返回一個(gè)函數(shù),該函數(shù)的參數(shù)還是一個(gè)函數(shù),還需要判斷是否提前停止迭代。這樣很不優(yōu)雅,本來這些是需要隱藏到幕后,由語言本身實(shí)現(xiàn)而不是由用戶去實(shí)現(xiàn)的。

其他語言中一個(gè)比較優(yōu)雅的迭代器實(shí)現(xiàn)方式是 Python 的生成器函數(shù),其方式如下:

def generator(num: int):  
    for i in range(num):  
        yield i

上面的代碼僅用3行就實(shí)現(xiàn)了同樣的功能,而且該函數(shù)里面無需返回函數(shù),無需判斷是否需要提前停止迭代。用戶只需關(guān)注如何生成數(shù)據(jù),然后通過一個(gè) yield 語句就可將數(shù)據(jù)傳給遍歷者。

4. 總結(jié)

Go 1.23版本之前,Go 官方?jīng)]有提供迭代器,需要用戶自己定義,很不方便。Go 1.23 開始,終于提供了官方的迭代器,彌補(bǔ)了 Go 語言在迭代器方面的缺失,方便了有相關(guān)需求的用戶,這是可喜的。

Go 語言追求簡單,少即是多的理念,這本無可厚非,不過之前的 Go 追求得有些極端了。近年來,Go 終于沒那么極端了,為 Go 語言本身和 Go 標(biāo)準(zhǔn)庫 添加了許多特性和功能。望 Go 早日成為主流編程語言。

到此這篇關(guān)于一文帶大家搞懂Go語言中的迭代器的文章就介紹到這了,更多相關(guān)Go語言迭代器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解如何在Go中使用Zap管理日志

    詳解如何在Go中使用Zap管理日志

    Zap提供了兩種類型的日志記錄器—Sugared?Logger和Logger,可以更好的管理日志,這篇文章主要為大家介紹了使用Zap管理日志的具體方法,需要的可以了解一下
    2023-07-07
  • Go語言操作數(shù)據(jù)庫及其常規(guī)操作的示例代碼

    Go語言操作數(shù)據(jù)庫及其常規(guī)操作的示例代碼

    這篇文章主要介紹了Go語言操作數(shù)據(jù)庫及其常規(guī)操作的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • 如何使用大學(xué)教育郵箱下載golang等軟件(推薦)

    如何使用大學(xué)教育郵箱下載golang等軟件(推薦)

    這篇文章主要介紹了如何使用大學(xué)教育郵箱下載goland等軟件,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-09-09
  • Go語言defer語句的三種機(jī)制整理

    Go語言defer語句的三種機(jī)制整理

    在本篇文章里小編給大家分享的是一篇關(guān)于Go語言defer語句的三種機(jī)制整理,需要的朋友們學(xué)習(xí)下吧。
    2020-03-03
  • Go Plugins插件的實(shí)現(xiàn)方式

    Go Plugins插件的實(shí)現(xiàn)方式

    目前 Plugins 僅在 Linux、FreeBSD 和 macOS 上受支持,且只支持 golang 調(diào)用,今天通過本文給大家介紹Go Plugins插件的實(shí)現(xiàn)方式,感興趣的朋友一起看看吧
    2021-08-08
  • 淺析Go語言中數(shù)組的使用

    淺析Go語言中數(shù)組的使用

    數(shù)組用于在單個(gè)變量中存儲相同類型的多個(gè)值,而不是為每個(gè)值聲明單獨(dú)的變量,這篇文章主要為大家介紹了Go語言中數(shù)組的簡單使用,需要?的可以參考下
    2023-08-08
  • 一文搞懂Go語言中文件的讀寫與創(chuàng)建

    一文搞懂Go語言中文件的讀寫與創(chuàng)建

    這篇文章主要為大家詳細(xì)介紹了Go語言中文件是如何實(shí)現(xiàn)讀寫與創(chuàng)建的,文中的示例代碼講解詳細(xì),對我們學(xué)習(xí)Go語言有一定幫助,需要的可以參考一下
    2022-07-07
  • Go語言sync.Pool對象池使用場景基本示例

    Go語言sync.Pool對象池使用場景基本示例

    這篇文章主要為大家介紹了Go語言sync.Pool對象池使用場景的基本示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-12-12
  • Go 請求兔子識別接口實(shí)現(xiàn)流程示例詳解

    Go 請求兔子識別接口實(shí)現(xiàn)流程示例詳解

    這篇文章主要為大家介紹了Go 請求兔子識別接口實(shí)現(xiàn)流程示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-04-04
  • 深入了解Golang中Slice切片的使用

    深入了解Golang中Slice切片的使用

    本文主要為大家詳細(xì)介紹了Golang中Slice切片的使用,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2023-02-02

最新評論