恰如其分的丑陋
用了段时间的golang,写点东西,强行把每年的post凑到3篇。
The Good
Language
做为C语系的明星级后辈,golang语法只能用平易近人来形容(跟lisp语系比起来)。只要是有一点其他C语系的背景,就算是没看完tutorial,不说写,读golang代码基本不会有任何困难。
学习曲线平缓且短 check√
作为2010年左右诞生的语言,modern的元素也一个都不差,reflection——有,GC——不断优化中,匿名函数——还行(不能用=>
略不爽),类型推断——姑且算吧,etc。
时尚 check√
简洁。不仅仅是少了每行一个的;
,或者是直接用方法名的大小写来区别“public”和“private”,就连语言的Specification也只有java的1/N长。
简约 check√
我最爱的几个小地方:
// swap
a, b = b, a
// byte manipulation
bs := []byte("ffff")
fmt.Printf("%x", bs)
// multiple expression for
for val, ok = dic[key]; ok {
// val blahblah
}
讨喜(???) check√
Go Tools
成熟的技术发展到一定阶段必定拥有自己的ecosystem,ecosystem的基石无非两点——开放&包管理。golang的开放不必说,全套代码就在那儿(compiler也用golang重写了,满足好奇心的成本够低了)。
golang的包管理也是简单的不行——源码分发,go get
完事。对比js和py,npm和pip都是强大的包管理工具,从各方面来说都比go get
强大不少(版本控制、可以做镜像等,现在的dep都还不是正式版本也比较神奇)。他们各自的生态体系中都诞生了不少不局限于nodejs和python的工具,比如tldr和thefuck。
golang的第三方工具不见多少(当然你可以说是stdlib足够强大),而且略显混乱(顺便吐槽dep和godep竟然是两个不懂的东西),但人家第一方的工具厉害的没朋友啊:
pprof
CPU和heap都能dump,针对http也有特化的包支持。总之profiler该有的东西都有,而且:
体贴到了这种程度!
BTW,CPU profile生成的SVG也不比Visual Studio里花哨的图差。
go vet
这段代码:
if (a != b || a != c) && cond {}
是会有warning的!!因为!=
是可以用xx定律提到外面去,而且代码本身的逻辑也读起来很不友好!是不是比def but not used
之类的warning有用很多(golang中的def but not used
是error)!
go fmt
终结“tab vs space”大战的神器,既然官方都认定了更好的格式,那还有什么理由不统一代码风格?不仅仅是一个项目的风格统一,而是所有项目的风格统一,想想都觉得很cooooooool(爸爸教你玩游戏写代码)。
google一下,吹gofmt的文章多得是。
Language-Level Parallel
之前写过不少关于javascript的async的文章,但始终没有一个结论,业界也并没有找到银弹。究其原因,无论是promise
还是async/await
,始终只是patch,补丁打的再多,能有一件新衣服好看?
问题不是actor模式或者“actress”模式多么好,而是原生级别/语法级别的并行支持,直接就决定了程序员写代码的思路!就像用C-like的语言处理集合,你第一反应是for
,而lisp-like,第一反应会是fold
有个形而上的视频值得一看
The Bad
no-sugar
爱好甜食,少了语法糖,多少有点不爽,比如
// 存疑,因为golang并不是OOP,而且this并不总是指针
func Struct.SomeFunc() {
this.Foo
}
strukt := SomeStruct {
A, // 同名的field自动赋值,like es2015
B,
C,
}
no-functional
无穷无尽的for让人心烦,没有map
没有filter
,也没法写出“underscore.js”来。因为虽然有high-order function,但是没有泛型。既然golang的author出于效率原因并没有选择泛型,那你除了写for也没有其他选择。golang的设计思路应该是productive和effective的平衡,泛型这个特性明显是取effective而舍productive的决定。但设计思路这种东西其实还是挺玄的,“符合设计思路”这件事,其实就是“作者想怎么定就怎么定”,所以才会有很多大神A用B语言不爽愤而发明C语言的故事。/摊手
error handling
显式的err handling,同泛型的取舍,有道理但我不喜欢,C式的错误处理让人感觉活在80年代。
The Ugly
终于可以点题了。
虽然在大神眼里,golang只算是个中等偏下的语言。 但这份“中等偏下”,IMHO,算得上是恰如其分。
拿另一个我用的多的语言举例子当反面教材——C#,C#每个版本里加入的语言特性和stdlib之多,简直是“互联网”式的。
C#好用吗?当然,你能想到的paradigm基本都能玩得转!但是C#2.0和C#6.0简直是两个语言,你写的C#和我写的C#也是两个语言。灵活的语言容易讨喜,写起来心情愉悦,殊不知“写代码一时爽,重构火葬场”。
你永远无法想象,在用别人的代码的时候,遇到ins.变量1
这种代码心里会是怎么个感受。(真人真事,人格担保)
Python这么多年来把定位相似的Ruby按在地上摩擦,就是因为Do one thing in one way
而不是Do one thing in 93244 ways
,golang同理,简洁的语法和gofmt,很好的完成了one way
的目标。比起python,golang更是多了效率(performance)的优势和原生的并行支持,备受追捧也是理所应当。
都2017年了,离C语言诞生都40多年了,可以说,最近10年诞生的所有语言都是DSL(domain specific)而没有general purpose了。 因为现在IT领域跟其他传统行业类似,也进入了细分的时代,比如AI和UI,虽然都有个I,但是从主流的开发语言到开发工具,基本上是没有走向统一的那天了。 就算一个新语言的定位是replace of C(Rust?不懂不乱说),那也是针对系统级编程的DSL。
golang就是云编程的DSL,因为docker和kubernets这种云时代的基础都是golang写的,正如unix是用C写的一样。
曾几何时,还被一些hello-world的文章误人子弟过,说什么golang是新一代的C,你家的C内存不透明反而封装好了线程池?
最后,还是一个我大学以来就坚持的观点——编程语言火不火,主要还是看用的人多不多,其他?都是废话。