写点什么

Go 中的 Channel 背后的设计哲学

用户头像
soolaugust
关注
发布于: 2020 年 12 月 24 日
Go中的Channel背后的设计哲学

最近在知乎上看到一段非常有趣的代码,用来解决“寻找10000以内的素数”问题。实现起来非常有趣,我们先看一下这段代码:







这段代码的思想基础是1978年的CSP (Communicating Sequential Processes)论文提出的CSP应用的经典问题:



Problem: To print in ascending order all primes less than 10000. Use an array of processes, SIEVE, in which each process inputs a prime from its predecessor and prints it. The process then inputs an ascending stream of numbers from its predecessor and passes them on to its successor, suppressing any that are multiples of the original prime.



中文翻译过来就是:



升序打印10000以内的素数,可以采用筛选法,也就是从2开始每找到一个素数就标记所有能被该素数整除的所有数。直到没有可标记的数,剩下的就都是素数



按照这个思路,我们可以用简单的方法来实现:



func printAllPrimes(r int) {
// 记录已经筛过的数据
notPrimeArray := make([]bool, r+1)
for i := 2; i <= r; i++ {
// 如果已经筛过,则跳过
if notPrimeArray[i] {
continue
}
// 当前肯定是个素数,所以直接打印
fmt.Printf("%d ", i)
// 开始筛选
for j := i + 1; j <= r; j++ {
// 已经筛过,跳过
if notPrimeArray[j] {
continue
}
// 如果能够整除,筛除
if j%i == 0 {
notPrimeArray[j] = true
}
}
}
}



这个使用循环做的,其实我们可以用递归来完成,也就是递归处理筛后的数据,这里我们就不写这种方法了,但是递归这个思想就是上面的代码所做的事情 (这里我们省略CSP和Go语言channel的相关内容,只做必要的描述,这些内容将在后面的内容专门讲,也是一个很有趣的设计):



func main() {
// CSP中输入和输出是一级单位,是基本的编程原语
// 这里定义了一个输入通道origin
// 一个等待输出通道wait
origin, wait := make(chan int), make(chan struct{})
// 调用主体递归函数
Processor(origin, wait)
// 输入数据,Golang中只有输入数据,输入通道才会被激活
for num := 2; num < 10; num++ {
origin <- num
}
// 关闭输入通道,代表数据输入结束
close(origin)
// 等待通道,等待程序结束
<-wait
}
func Processor(seq chan int, wait chan struct{}) {
go func() {
prime, ok := <-seq
// 全部筛完的话是取不到任何输入的,这时结束等待,程序结束
if !ok {
close(wait)
return
}
// 和上面一样,当前是素数,直接打印
fmt.Println(prime)
// 定义新的输入通道,这个就是筛后的数据
out := make(chan int)
// 递归调用
Processor(out, wait)
// 输入筛后的数据
for num := range seq {
if num%prime != 0 {
out <- num
}
}
// 结束输入,代表本轮输入结束
close(out)
}()
}



这里和传统的递归算法大体上没什么区别,我们可以看到这里多的是通道,也就是CSP中的设计哲学:用通信共享内存来实现并发。我们在以后的文章会讲解到为什么CSP这么重要,它是如何做到让编写并发程序变得像串行程序一样简单。





参考链接



发布于: 2020 年 12 月 24 日阅读数: 38
用户头像

soolaugust

关注

公众号:雨夜随笔 2018.09.21 加入

公众号:雨夜随笔

评论

发布
暂无评论
Go中的Channel背后的设计哲学