搜索
首页后端开发Golang了解 Go 中的迭代器:一次有趣的探索!

Understanding Iterators in Go: A Fun Dive!

如果您是一名 Go 程序员,您可能在 Go 1.22 中多次听说过迭代器,尤其是在 Go 1.23 中。但也许您仍然摸不着头脑,想知道它们为什么有用或者何时应该使用它们。嗯,您来对地方了!让我们首先了解迭代器在 Go 中的工作原理以及它们为何如此有用。

一个简单的转换:还没有迭代器

假设我们有一个数字列表,我们希望将每个数字加倍。我们可以使用如下所示的简单函数来完成此操作:

package main

import (
    "fmt"
)

func NormalTransform[T1, T2 any](list []T1, transform func(T1) T2) []T2 {
    transformed := make([]T2, len(list))

    for i, t := range list {
        transformed[i] = transform(t)
    }

    return transformed
}

func main() {
    list := []int{1, 2, 3, 4, 5}
    doubleFunc := func(i int) int { return i * 2 }

    for i, num := range NormalTransform(list, doubleFunc) {
        fmt.Println(i, num)
    }
}

运行此代码时会发生以下情况:

0 2
1 4
2 6
3 8
4 10

很简单,对吧?这是一个基本的通用 Go 函数,它接受任何类型 T1 的列表,对每个元素应用转换函数,并返回一个新列表,其中包含任何类型 T2 的转换后的列表。如果您了解 Go 泛型

,那么很容易理解

但是如果我告诉你还有另一种方法来处理这个问题——使用迭代器呢?

输入迭代器!

现在,让我们看看如何使用迭代器进行相同的转换:

package main

import (
    "fmt"
)

func IteratorTransform[T1, T2 any](list []T1, transform func(T1) T2) iter.Seq2[int, T2] {
    return func(yield func(int, T2) bool) {
        for i, t := range list {
            if !yield(i, transform(t)) {
                return
            }
        }
    }
}

func main() {
    list := []int{1, 2, 3, 4, 5}
    doubleFunc := func(i int) int { return i * 2 }

    for i, num := range NormalTransform(list, doubleFunc) {
        fmt.Println(i, num)
    }
}

运行之前,您必须确保您的 Go 版本是 1.23。输出完全相同:

0 2
1 4
2 6
3 8
4 10

但是等等,为什么我们需要一个迭代器?那不是更复杂吗?让我们深入探讨一下差异。

为什么使用迭代器?

乍一看,对于像转换列表这样简单的事情,迭代器似乎有点过度设计。但当您运行基准测试时,您就会开始明白为什么它们值得考虑!

让我们对这两种方法进行基准测试,看看它们的表现如何:

package main

import (
    "testing"
)

var (
    transform = func(i int) int { return i * 2 }
    list      = []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
)

func BenchmarkNormalTransform(b *testing.B) {
    for i := 0; i 



<p>这是初始基准测试结果:<br>
</p>

<pre class="brush:php;toolbar:false">BenchmarkNormalTransform-8      41292933                29.49 ns/op
BenchmarkIteratorTransform-8    1000000000               0.3135 ns/op

哇!这是一个巨大的差异!但是等等——这里有一点不公平。 NormalTransform 函数返回一个完全转换的列表,而 IteratorTransform 函数仅设置迭代器,尚未转换列表。

让我们通过完全循环迭代器来使其公平:

func BenchmarkIteratorTransform(b *testing.B) {
    for i := 0; i 



<p>现在结果更加合理了:<br>
</p>

<pre class="brush:php;toolbar:false">BenchmarkNormalTransform-8      40758822                29.16 ns/op
BenchmarkIteratorTransform-8    53967146                22.39 ns/op

好吧,迭代器有点快。为什么?因为 NormalTransform 在返回之前会在内存中(在堆上)创建一个完整的转换列表,而迭代器会在循环遍历它时进行转换,从而节省时间和内存。

在此处阅读有关堆栈和堆的更多信息

当你不需要处理整个列表时,迭代器的真正魔力就会发生。让我们对一个场景进行基准测试,在转换列表后我们只想找到数字 4:

func BenchmarkNormalTransform(b *testing.B) {
    for i := 0; i 



结果不言而喻:

package main

import (
    "fmt"
)

func NormalTransform[T1, T2 any](list []T1, transform func(T1) T2) []T2 {
    transformed := make([]T2, len(list))

    for i, t := range list {
        transformed[i] = transform(t)
    }

    return transformed
}

func main() {
    list := []int{1, 2, 3, 4, 5}
    doubleFunc := func(i int) int { return i * 2 }

    for i, num := range NormalTransform(list, doubleFunc) {
        fmt.Println(i, num)
    }
}

在这种情况下,迭代器要快得多!为什么?因为迭代器不会转换整个列表 - 一旦找到您要查找的结果,它就会停止。另一方面,即使我们只关心一项,NormalTransform 仍然会转换整个列表。

结论:何时使用迭代器?

那么,为什么在 Go 中使用迭代器?

  • 效率:如果不需要,迭代器可以不处理整个列表,从而节省时间和内存。
  • 灵活性:它们使您能够有效地处理大型数据集,特别是在处理数据流或需要提前停止时。 但请记住,迭代器的理解和实现可能有点棘手。当您需要额外的性能提升时,尤其是在您不需要预先处理整个列表的情况下,请使用它们。

迭代器:它们快速、灵活且有趣——一旦你掌握了它们!

以上是了解 Go 中的迭代器:一次有趣的探索!的详细内容。更多信息请关注PHP中文网其他相关文章!

声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
去其他语言:比较分析去其他语言:比较分析Apr 28, 2025 am 12:17 AM

goisastrongchoiceforprojectsneedingsimplicity,绩效和引发性,butitmaylackinadvancedfeatures and ecosystemmaturity.1)

比较以其他语言的静态初始化器中的初始化功能比较以其他语言的静态初始化器中的初始化功能Apr 28, 2025 am 12:16 AM

Go'sinitfunctionandJava'sstaticinitializersbothservetosetupenvironmentsbeforethemainfunction,buttheydifferinexecutionandcontrol.Go'sinitissimpleandautomatic,suitableforbasicsetupsbutcanleadtocomplexityifoverused.Java'sstaticinitializersoffermorecontr

GO中初始功能的常见用例GO中初始功能的常见用例Apr 28, 2025 am 12:13 AM

thecommonusecasesfortheinitfunctionoare:1)加载configurationfilesbeforeThemainProgramStarts,2)初始化的globalvariables和3)runningpre-checkSorvalidationsbeforEtheprofforeTheProgrecce.TheInitFunctionIsautefunctionIsautomentycalomationalmatomatimationalycalmatemationalcalledbebeforethemainfuniinfuninfuntuntion

GO中的频道:掌握际际交流GO中的频道:掌握际际交流Apr 28, 2025 am 12:04 AM

ChannelsarecrucialingoforenablingsafeandefficityCommunicationBetnewengoroutines.theyfacilitateSynChronizationAndManageGoroutIneLifeCycle,EssentialforConcurrentProgramming.ChannelSallSallSallSallSallowSallowsAllowsEnderDendingAndReceivingValues,ActassignalsignalsforsynChronization,and actassignalsynChronization and andsupppor

包装错误:将上下文添加到错误链中包装错误:将上下文添加到错误链中Apr 28, 2025 am 12:02 AM

在Go中,可以通过errors.Wrap和errors.Unwrap方法来包装错误并添加上下文。1)使用errors包的新功能,可以在错误传播过程中添加上下文信息。2)通过fmt.Errorf和%w包装错误,帮助定位问题。3)自定义错误类型可以创建更具语义化的错误,增强错误处理的表达能力。

使用GO开发时的安全考虑使用GO开发时的安全考虑Apr 27, 2025 am 12:18 AM

Gooffersrobustfeaturesforsecurecoding,butdevelopersmustimplementsecuritybestpracticeseffectively.1)UseGo'scryptopackageforsecuredatahandling.2)Manageconcurrencywithsynchronizationprimitivestopreventraceconditions.3)SanitizeexternalinputstoavoidSQLinj

了解GO的错误接口了解GO的错误接口Apr 27, 2025 am 12:16 AM

Go的错误接口定义为typeerrorinterface{Error()string},允许任何实现Error()方法的类型被视为错误。使用步骤如下:1.基本检查和记录错误,例如iferr!=nil{log.Printf("Anerroroccurred:%v",err)return}。2.创建自定义错误类型以提供更多信息,如typeMyErrorstruct{MsgstringDetailstring}。3.使用错误包装(自Go1.13起)来添加上下文而不丢失原始错误信息,

并发程序中的错误处理并发程序中的错误处理Apr 27, 2025 am 12:13 AM

对效率的Handleerrorsinconcurrentgopragrs,UsechannelstocommunicateErrors,EmparterRorwatchers,InsterTimeouts,UsebufferedChannels和Provideclearrormessages.1)USEchannelelStopassErstopassErrorsErtopassErrorsErrorsFromGoroutInestotheStothemainfunction.2)

See all articles

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

Video Face Swap

Video Face Swap

使用我们完全免费的人工智能换脸工具轻松在任何视频中换脸!

热工具

安全考试浏览器

安全考试浏览器

Safe Exam Browser是一个安全的浏览器环境,用于安全地进行在线考试。该软件将任何计算机变成一个安全的工作站。它控制对任何实用工具的访问,并防止学生使用未经授权的资源。

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

mPDF

mPDF

mPDF是一个PHP库,可以从UTF-8编码的HTML生成PDF文件。原作者Ian Back编写mPDF以从他的网站上“即时”输出PDF文件,并处理不同的语言。与原始脚本如HTML2FPDF相比,它的速度较慢,并且在使用Unicode字体时生成的文件较大,但支持CSS样式等,并进行了大量增强。支持几乎所有语言,包括RTL(阿拉伯语和希伯来语)和CJK(中日韩)。支持嵌套的块级元素(如P、DIV),

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

Atom编辑器mac版下载

Atom编辑器mac版下载

最流行的的开源编辑器