编程 Go1.23引入了函数类型的range特性,允许开发者以标准化的方式遍历自定义容器

2024-11-18 23:41:54 +0800 CST views 948

函数类型的 Range - Go 编程语言

简介

Go 1.23 引入了一个新特性:函数类型的 range。本文将详细介绍为什么要添加这个特性,它是什么,以及如何使用它。

为什么要添加这个特性?

自 Go 1.18 以来,Go 语言已经支持编写新的泛型容器类型。例如,我们可以创建一个基于 map 实现的泛型 Set 类型:

type Set[E comparable] struct {
    m map[E]struct{}
}

Set 类型可以提供方法来添加元素和检查元素是否存在:

func (s *Set[E]) Add(v E) {
    s.m[v] = struct{}{}
}

func (s *Set[E]) Contains(v E) bool {
    _, ok := s.m[v]
    return ok
}

然而,遍历集合元素是很常见的需求。我们希望为用户提供一种标准化的方式来遍历 Set 中的元素。

推送元素的遍历方式

我们可以为 Set 添加一个方法,接受一个函数作为参数,并将每个元素推送给该函数。我们称这个方法为 Push

func (s *Set[E]) Push(yield func(E) bool) {
    for v := range s.m {
        if !yield(v) {
            break
        }
    }
}

用户可以使用 Push 方法打印 Set 中的所有元素:

s.Push(func(v string) bool {
    fmt.Println(v)
    return true
})

拉取元素的遍历方式

另一种方法是返回一个函数,每次调用该函数都会返回集合中的下一个值。我们可以称这个方法为 Pull,并实现如下:

func (s *Set[E]) Pull() (next func() (E, bool), stop func()) {
    ch := make(chan E)
    done := make(chan struct{})
    go func() {
        defer close(ch)
        for v := range s.m {
            select {
            case ch <- v:
            case <-done:
                return
            }
        }
    }()
    return func() (E, bool) {
            v, ok := <-ch
            return v, ok
        },
        func() {
            close(done)
            for range ch {
            }
        }
}

我们可以这样使用 Pull 方法:

next, stop := s.Pull()
defer stop()
for {
    v, ok := next()
    if !ok {
        break
    }
    fmt.Println(v)
}

Go 1.23 的改进

Go 1.23 为 for/range 语句添加了对用户定义容器类型的支持,并引入了标准化的迭代器。新的 range 支持函数类型,只要这些函数符合特定的签名。

我们可以使用函数类型 range 来遍历自定义容器,比如我们的 Set。假设我们为 Set 定义一个 All 方法返回迭代器:

func (s *Set[E]) All() iter.Seq[E] {
    return func(yield func(E) bool) {
        for v := range s.m {
            if !yield(v) {
                return
            }
        }
    }
}

这样,我们可以通过 for/range 轻松遍历 Set 中的所有元素:

for v := range s.All() {
    fmt.Println(v)
}

结语

Go 1.23 的函数类型 range 提供了一种更标准化、更易用的方式来遍历自定义容器。通过这个新特性,开发者可以更轻松地构建泛型容器,并以更简洁的方式实现容器元素的遍历。

复制全文 生成海报 Go语言 编程 泛型 开发

推荐文章

JavaScript中设置器和获取器
2024-11-17 19:54:27 +0800 CST
PHP服务器直传阿里云OSS
2024-11-18 19:04:44 +0800 CST
推荐几个前端常用的工具网站
2024-11-19 07:58:08 +0800 CST
关于 `nohup` 和 `&` 的使用说明
2024-11-19 08:49:44 +0800 CST
Golang中国地址生成扩展包
2024-11-19 06:01:16 +0800 CST
全新 Nginx 在线管理平台
2024-11-19 04:18:33 +0800 CST
跟着 IP 地址,我能找到你家不?
2024-11-18 12:12:54 +0800 CST
WebSQL数据库:HTML5的非标准伴侣
2024-11-18 22:44:20 +0800 CST
实现微信回调多域名的方法
2024-11-18 09:45:18 +0800 CST
Nginx负载均衡详解
2024-11-17 07:43:48 +0800 CST
联系我们
2024-11-19 02:17:12 +0800 CST
ElasticSearch简介与安装指南
2024-11-19 02:17:38 +0800 CST
一个简单的打字机效果的实现
2024-11-19 04:47:27 +0800 CST
MySQL 主从同步一致性详解
2024-11-19 02:49:19 +0800 CST
php常用的正则表达式
2024-11-19 03:48:35 +0800 CST
php腾讯云发送短信
2024-11-18 13:50:11 +0800 CST
#免密码登录服务器
2024-11-19 04:29:52 +0800 CST
企业官网案例-芊诺网络科技官网
2024-11-18 11:30:20 +0800 CST
解决python “No module named pip”
2024-11-18 11:49:18 +0800 CST
你可能不知道的 18 个前端技巧
2025-06-12 13:15:26 +0800 CST
一些实用的前端开发工具网站
2024-11-18 14:30:55 +0800 CST
Nginx 性能优化有这篇就够了!
2024-11-19 01:57:41 +0800 CST
PHP来做一个短网址(短链接)服务
2024-11-17 22:18:37 +0800 CST
mysql 计算附近的人
2024-11-18 13:51:11 +0800 CST
软件定制开发流程
2024-11-19 05:52:28 +0800 CST
程序员茄子在线接单