找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 103092|回复: 0

Go语言不简单

[复制链接]

该用户从未签到

发表于 2021-3-3 10:41:15 | 显示全部楼层 |阅读模式

您需要 登录 才可以下载或查看,没有账号?立即注册

×
【CSDN 编者按】相信你跟我一样,在以往听到的言论中都认为 Go 语言很简单,很容易学,但是事实真的是这样的吗?反方队伍认为 Go 语言并不简单,下面请反方辩手发言~
作者 | Martin TournoijGo 不是一种很简单的编程语言。尽管它的许多方面都很简单:语法很简单,大多数语义也很简单。然而,语言不仅仅是语法,我们希望利用它编写出实用的代码。利用 Go 编写有用的代码并不总是那么容易。
事实证明,通过某种方式将一些简单的功能组合在一起,编写出有用的代码可能会非常棘手。在 Ruby 中,如何删除某个数组中的一项?list.delete_at(i)。如何通过值删除条目?list.delete(value)。非常简单!
然而在 Go 中,事情可没有那么容易,为了删除索引 i,你需要执行以下操作:
list= append(list[:i,,list[i+1:,...)ifl != v {list[n, = ln++}}这未免也太复杂了?也未必,我认为即使没有 Go 语言经验,大多数程序员也可以看懂上述代码。但它确实不简单。我这个人比较懒,我会从 SliceTricks 上复制这类代码,因为我想专心解决实际问题,不想为这类小事苦恼。
此外,Go 语言也很容易出现使用错误或性能不佳的情况,特别是对于经验不足的程序员而言。例如,我们来比较一下:将上述复制到一个新数组,和复制到一个新的预分配数组(make(string, 0]len(list))):
InPlace116ns/op 0 B/op 0 allocs/opNewArrayPreAlloc525ns/op 896 B/op 1 allocs/opNewArray1529ns/op 2040 B/op 8 allocs/op尽管在大多数情况下 1529ns 足够快了,而且也不必过分担心,但是在许多情况下,性能确实很重要,而且拥有能保证实现最佳性能的 list.delete(value)是非常有必要的。

再举一个例子:goroutine。“使用 goroutine 并不难,你只需要添加关键字 go,就可以了!”没错,这样确实可以了,但是如果我需要同时运行 500 万个 goroutine 呢?到时候,你会纳闷,所有内存都去哪儿了?而且你很难避免意外“泄漏”goroutine。
有许多模式可以限制 goroutine 的数量,但哪一种都不简单。下面就是一个简单的例子:
var(jobs =20// Run 20 jobs in total.running =make(chanbool,3)// Limit concurrent jobs to 3.done =make(chanbool)// Signal that all jobs are done.)fori :=1; i <= jobs; i++ {running <-true//Fill running; this will block and wait if it's already full.// Start a job.gofunc(iint){deferfunc{<-running// Drain runningso new jobs can be added.ifi == jobs {// Last job, signal that we're done.done <-true}}// "dowork"time.Sleep(1*time.Second)fmt.Println(i)}(i)}<-done// Wait until all jobs are done.fmt.Println("done")我加了一些注释是有原因的:对于不熟悉 Go 的人来说,这段代码非常难以理解。上述代码也不能确保数字会按照一定的顺序输出(这可能是一项需求,当然也可能不是)。
Go 的并发原语很简单且易于使用,但是将它们组合起来,解决常见的现实问题就没有那么简单了。

RichHickey 在“Simple Made Easy”中提出,我们不应该将“简单”与“易于编写”混为一谈:即便你只需编写一两行代码,也并不意味着底层的概念很简单(这里的简单指的是浅显易懂)。
这句话值得人寻味。在大多数情况下,我们不应该为了“易于编写”而牺牲“简单”。但这并不意味着我们不应该考虑如何让编程更加简单。即便概念很简单,也并不意味着易于使用,人们可能会错误地使用,或使用的方式会引发 bug。将 Hickey 的论点推到极致,就会出现 Brainfuck 之类语言,当然这很愚蠢。
理想情况下,编程语言应该减少推理其行为所需的认知负担,增加这种认知负担的方法有很多:复杂的语言功能就是其中之一;而人们不得不花费精力实现一些简单的概念也是一种负担,因为我需要多考虑一段代码。尽管我不太关心代码格式或语法选择,但我认为减少阅读代码时的认知负担很重要。
缺少泛型是导致 Go 不那么简单的部分原因。现在很难实现 slices 包之类以通用的方式完成的操作。而泛型可以让这成为可能,同时也会让编程变得更复杂(使用了更多的语言功能),但是它们也可以让编程更加容易,并降低其他方面的复杂性。

这些是无法克服的问题吗?不,我仍然会使用 Go,而且也会一如既往地喜欢 Go。但是,我不认为 Go 是你“可以在 5~10 分钟之内学会的语言”。

归根结底,学习语言不仅仅要学习编写 if 和 for 的语法,你需要学习的是思维方式。我见过许多 Python 或 C#开发人员尝试在 Go 语言中实现那些语言的某些概念或模式。常见的做法包括将结构嵌入作为继承,将 panics 作为异常,通过 interface{}实现“伪动态编程”等等。这些做法很难取得良好的结果。
当第一次编写 Go 程序时,我也犯了同样的错误,这是很自然的事情。在刚接触 Ruby 的时候,我曾尝试用 Ruby 编写 Python 代码(由于这两种语言很相似,所以结果相对好一点,但仍然有很多奇怪的做法,比如使用 for 循环)。
这就是为什么我不喜欢人们通过 Go 教程学习这门语言的原因,教程只会讲解基本的语法,还有其他的一些知识。这只能让你大致感受一下 Go 语言,但并不能帮助你真正学习这门语言。
英文标题:Go is not an easy language

声明:本文为 CSDN 翻译,转载请注明出处。



☞尴尬!因软件 Bug ,美国数百名囚犯释放后无法出狱
回复

使用道具 举报

网站地图|页面地图|文字地图|Archiver|手机版|小黑屋|找资源 |网站地图

GMT+8, 2024-11-2 23:25

Powered by Discuz! X3.5

© 2001-2024 Discuz! Team.

快速回复 返回顶部 返回列表