Golang Go语言中感觉引入了 chan 后,go 测序的阅读不是那么线性

Golang Go语言中感觉引入了 chan 后,go 测序的阅读不是那么线性

这个不一定对,只是我的一个感觉。

举个例子,https://github.com/rissw/not_yet_hit_the_wall/blob/main/03-blockread-concurrent/blockread-concurrent.go 这个作者使用并行的方式去统计大文件里面的行数,速度的确很快,几乎和 wc -l 差不多。

但是理解起来真是费劲,比 00-readfile 串行读取统计难度高许多。(但是也快很多,几十倍吧)

后来我一边阅读一边画图才理顺了。感觉 go 的程序需要配个图理解一下啊。

blockread.png

(画图的时候把变量名也重构了一下更符合自己的理解,可能和源程序的命名稍有不同,大致结构是一样的)


更多关于Golang Go语言中感觉引入了 chan 后,go 测序的阅读不是那么线性的实战教程也可以访问 https://www.itying.com/category-94-b0.html

20 回复

chan 的阅读性跟 goto 一样,是会降低代码阅读性

但是好在 chan 场景有限,不像 goto 真的想用可以搞的飞起…

更多关于Golang Go语言中感觉引入了 chan 后,go 测序的阅读不是那么线性的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


图用啥画的

所以我用 C# 感觉 await async 那样阅读更方便 上下文逻辑也不会割裂

count 改成用 atomicInt 可以省掉个 chan

如果要安全的关闭 chan 会更加恶心,会有各种依赖死锁

go-zero 里有个 mapreduce 组件,可以了解一下看看是不是你想要的 https://gocn.vip/topics/10941

楼主这个图画得真好,是用啥工具画的啊?

用一个 chan 就好了,没必要三个。count 可以按楼上说的用 atomic value

#7
#2

visio

看到过 chan chan chan 的,选择死亡

你那是没见过 channel 嵌套,真是难为编辑器了

chan:这锅我不背

那么是 go 的代码好读还是 wc 的好读呢

#4
#8

确实,我是在研究这一系列文章的时候 https://marcellanz.com/post/file-read-challenge/ 看到了现在这个 repo 的。之前这篇写的蛮好的,确实有减少 chan,内存优化等等之类的技巧。

1. https://boyter.org/posts/file-read-challange/
2. Using Java to Read Really, Really Large Files
3. Processing Large Files in Java
4. Processing Large Files – Java, Go and ‘hitting the wall’

https://github.com/vietvudanh/really-large-file python rust go java scala
https://github.com/rissw/not_yet_hit_the_wall


#11 是啊 ,这种代码咋读,自己写的还好,看别人写的真是一脸懵逼。

正常情况下也不会这样写代码。如果提前取一下文件大小,然后直接分配下每个线程负责的 offset,然后多线程每个线程各自打开文件,seek 到 offset,用 SIMD 找换行符,性能应该还能更快。

虽然是 Go 的拥趸,但是还真是觉得 chan 的设计就是一坨排泄物,即使一个老手要用好 chan 也难上加难。
一些入门读物都会喜欢用 CSP 这种高大上的词汇来吓唬人。。
最神奇的设计就是,向已经关闭的 chan 发送数据会导致 panic,别跟我提背后的设计理由,我都读了无数遍了。
本来能在底层暴露一个简单的借口,导致为了写安全的代码,代码越写越难看,理解起来越费劲。

等会儿,楼主你这 ID 有来头啊

对啊,还不如学其他语言的 queue,多加了一堆概念,好处却没增加多少

你要考虑,如果是 c/cpp 那些,要自己写信号量 /条件量+queue,虽然也是简单的玩意,但对于逻辑程序员占 80%的程序员群体中的这大部分人,已经是一道天堑鸿沟了,chan 可以让你直接拿来就用了。

稍微复杂点的功能都可能需要去处理并发相关的事情,真的不算事。所以你说的缺点,可能对于长期做 web 接口开发 CURD 人员来说,确实是难了点。如果都是按照 CURD 的标准来要求开发者,那很多基础设施类的东西都没几个人能做了。即使是其他语言很方便,但承担造轮子任务的人仍然要面对大量的复杂。

chan 的这点复杂,应该是自己级别飞升时必须克服的一道基本功修炼流程,而不是被这么点复杂把自己逼在舒适区里只靠业务经验提高履历含金量。

在Go语言中,chan(通道)的引入确实为并发编程带来了极大的便利,但同时也使得代码的阅读和理解变得非线性。这是因为在Go中,通过goroutinechannel可以轻松地实现并发执行和数据交换,而这种并发性自然打破了传统顺序执行的线性结构。

为了更好地理解和阅读引入chan后的Go代码,你可以采取以下几个策略:

  1. 明确并发逻辑:首先,要清晰地理解代码中哪些部分是在并发执行的。这通常涉及到go关键字的使用以及channel的读写操作。

  2. 追踪数据流动:通过channel,数据可以在不同的goroutine之间传递。因此,你需要仔细追踪数据的流动路径,以理解各个goroutine之间的依赖关系。

  3. 使用同步原语:在并发编程中,同步是非常重要的。Go提供了诸如sync.WaitGroupsync.Mutex等同步原语来帮助你确保各个goroutine之间的正确执行顺序。

  4. 编写清晰的代码:良好的编码习惯对于阅读和理解并发代码至关重要。使用有意义的变量名、注释以及合理的代码结构可以显著提高代码的可读性。

总之,虽然chan的引入使得Go代码的阅读变得不那么线性,但通过明确并发逻辑、追踪数据流动、使用同步原语以及编写清晰的代码,你仍然可以很好地理解和维护这些并发程序。

回到顶部