go 新特性 range over func 没怎么看懂。。。。写库的时候用吗?

186 天前
dyllen  dyllen

go1.23 新的正式特性 range over func 看了下没怎么看懂。。。

for range 返回一个函数,函数里面还是 for range 或者就 for 循环:

func Backward[E any](s []E) func(func(int, E) bool) {
    return func(yield func(int, E) bool) {
        for i := len(s) - 1; i >= 0; i-- {
            if !yield(i, s[i]) {
                return
            }
        }
        return
    }
}

func main() {
    sl := []string{"hello", "world", "golang"}
    for i, s := range Backward(sl) {
        fmt.Printf("%d : %s\n", i, s)
    }
}

Backward这个函数这形式看起来还真有点复杂,不好理解。。。。可能例子不是相应场景下需要的,看半天没理解。 感觉一般都用不上。

10587 次点击
所在节点   Go 编程语言  Go 编程语言
105 条回复
assassing
assassing
186 天前
按照写 Python 的经验,迭代器没有非用不可的场景,虽然它很简单。

Go 语言中宁可牺牲简单性,也不愿意引入新关键字,我是理解不了的。去原帖看了下,作者认为这样实现迭代器工作量比较小...
hxtheone
hxtheone
186 天前
个人感觉 Go 语言一直对库的调用者比编写者更友好, 但是这个特性在写库的时候简直是太磨人了, 配上泛型和又臭又长的匿名函数简直是没眼看
kiripeng
kiripeng
186 天前
这特性就是一坨,我都懒得升级
dyllen
dyllen
186 天前
@assassing 不也增加了 yield 关键字吗,把复杂性丢给我使用者。。。
KaynW
KaynW
186 天前
确实丑的可以,层级这么多,}}}}看着丑的很
loveuer
loveuer
186 天前
@dyllen #24 没增加,yield 是个匿名函数
dyllen
dyllen
186 天前
@loveuer `func(yield func(int, E) bool)`这里面的这个 yield 看起来不像函数呀。
cmdOptionKana
cmdOptionKana
186 天前
挺好的啊,Go 的这个函数就像一个外皮透明的动物,让你一眼看见里面的食道和胃具体是怎样消化食物的,非常直白。写 Go 真的让人头脑清晰,而且过一段时间回头看也条理清晰,比一堆语法糖好多了。
stevenshuang
stevenshuang
186 天前
@dyllen yield 没有增加,yield 就是那个函数的命名。https://go.dev/ref/spec#Keywords
leonshaw
leonshaw
186 天前
@dyllen yield 是参数名。这东西看起来就是 for-range 简单地帮你生成了一个回调函数。
it := Backward(sl)
cb := func(i int, s string) bool {
fmt.Printf("%d : %s\n", i, s)
return true
}
it(cb)
vfs
vfs
186 天前
@sagaxu 感觉从支持泛型的那一版就已经走下坡路了.
assassing
assassing
186 天前
@cmdOptionKana 噗,你这比喻很到位,大中午的不想吃饭了都


@dyllen 不是关键字,随便叫什么都成,关键字你可以查看这里: https://github.com/golang/go/blob/release-branch.go1.23/src/builtin/builtin.go
b4115Z4mRAz9P8EA
b4115Z4mRAz9P8EA
186 天前
@PTLin 这个特性,也被大佬抨得一塌糊涂,太复杂了。
这个特性除了炫耀自己编程厉害,并没有什么特殊的好处,其功能用其他方式同样能完成,还容易读。说与其弄这些,不如提升性能。
MoYi123
186 天前
Backward 里的 func 套 func 是函数式编程里的常见的惰性求值的写法. 不觉得有什么问题.
ChrisFreeMan
186 天前
我觉得还好,多看几眼觉得很合理。
sophos
186 天前
我感觉这个特性是很有用的,主要是用在提供常用操作的组件中,调用方的代码还是比较直观的

至于写组件的时候,可以直接用 iter.Seq 或 iter.Seq2 ,别直接用匿名函数就行,还好吧
dacapoday
186 天前
高阶函数而已,比较取巧,但合理。
Nazz
186 天前
笑了, 这么多人又菜又爱喷

经常写数据结构的人不会对这个接口感到陌生:

```go
type Ranger[K comparable, V any] interface {
Range(k K, v V) bool
}
```

有了 range over func 语法糖, 可以非常方便地返回上层函数
Trim21
186 天前
golang 为了不加这个 yield 关键词真是煞费苦心…

这个新功能还有个离谱的地方是标准库里 iter.Pull 的实现方法,直接魔改运行时…
dule
186 天前
以前看过 go 语言的代码就觉得这玩意语法是真丑陋啊,太不直观了

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1066038

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX