Golang中如何将通道的值收集到切片中?(需要工具方法,可能来自go-funk)

Golang中如何将通道的值收集到切片中?(需要工具方法,可能来自go-funk) go-funk 中是否有将通道中的值收集到切片中的功能?是否有任何库提供此功能?

我不想自己实现这个功能。

6 回复

你好 @skillian

为什么每次需要解决相同问题时,都要在文件中多写7行代码?是否有现成的库可以实现这个功能?

更多关于Golang中如何将通道的值收集到切片中?(需要工具方法,可能来自go-funk)的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


@skillian

两种方案各有利弊。我认为这需要每位开发者或团队根据具体情况自行决定。

那么,解决方案是什么呢?我曾对 go-funk 抱有希望,但看起来它确实无法做到这一点。

go-funk 的作者在看这个论坛吗?我可以助你一臂之力。

Go-funk 无法处理通道,因为从设计上来说,你想要的结果是不可预测的。你传递了哪个通道?你如何防止通道阻塞?这里外部上下文很重要。在我看来,go-funk 是一组独立的函数,它们所做的正是函数式语言通过管道操作符和声明式风格所做的事情。

为什么不自己实现这个功能呢?看起来你可以直接这样做:

func readEverythingFromChannel(ch chan *Something) []*Something {
    somethings := make([]*Something)
    for s := range ch {
        somethings = append(somethings, s)
    }
    return somethings
}

我想我们都有不同的看法。从我的角度来看,问题应该是“既然我能写七行代码,为什么要依赖一个库呢?”

并非要引发争论,但考虑到在@heidi的上一篇文章中,他们提到:

大多数时候我都在探讨一些哲学性的问题。

我认为引用Go谚语中的一条可能很贴切:“一点复制好过一点依赖”

话虽如此,我并不知道有哪个库能实现这个功能,但一些旨在让Go更具函数式风格的项目可能会接受一个PR。在Go 1.18及以后的版本中,你可以创建自己的包,放入我上面代码的泛型版本,然后从你的其他项目中引用它,这样你就不必重复编写了。

在Go语言中,标准库没有提供直接将通道值收集到切片的工具方法。不过,你可以使用go-funk库的ToSlice函数来实现这一需求。以下是一个示例代码:

package main

import (
	"fmt"
	"github.com/thoas/go-funk"
)

func main() {
	ch := make(chan int, 5)
	ch <- 1
	ch <- 2
	ch <- 3
	close(ch)

	slice := funk.ToSlice(ch).([]int)
	fmt.Println(slice) // 输出: [1 2 3]
}

go-funkToSlice函数可以处理通道输入,并返回对应的切片。需要注意的是,通道在传递给ToSlice之前应当被关闭,以确保所有值都能被正确收集。如果通道未关闭,ToSlice只会收集当前可用的值,然后返回。

对于更复杂的场景,比如处理无限通道或需要并发收集的情况,你可能需要结合其他模式。但针对基本的通道到切片的转换,go-funkToSlice函数是一个有效的解决方案。

回到顶部