(原发于 GitHub Pages,2019-01-01 23:22:43)

2019 年,我回来了。

不知不觉中,我入 PHP 的坑已经 3 年有余,入 Go 的坑也大半年了。作为不评论不舒服斯基星人,自然要对 Go 品头论足一番的。

总的一句话,Go 的一些特性确实恰到好处,然而更多的地方却是平庸、繁琐、束缚,以至于我想不到它是适合哪些场景的。

静态语言里,C、C++ 有着明显的适用领域:你要想老老实实写程序,不玩任何花招,就用 C 吧,至少你能掌控一切,实在想玩你还有宏这个大杀器;你要想玩点花招,那就用 C++,代价就是需要自身水平更高,能掌控到多大层次就写多大层次,不懂的不要不懂装懂去用,总体来说还是安全的。

脚本语言里,如果要随便写点什么工具,python 啥的挺方便的;写点网络的,就用世界上最好的语言 PHP 吧。什么?你说 Java?实在没办法,体量太大,公司要你用你就用吧。不过就其本质而言,其实 Java 和今天的主角——Go 是同一类的。不是说他们语法像,是指应用场景(不过这个领域拿 PHP 写显然会更爽)。

嗯——为了表达出真实的意思,我想用词稍微犀利点,请先做一下心理建设。

我不怎么懂 Java,就我浅薄的了解而言,如果你的公司、团队有很多傻逼,甚至你自己也是,业务上又正好可以用 Java 界的一些现成的框架、组件,那么用 Java 肯定是没错的啦。它确实有一种魔力,让你无论多傻逼,也绝对写不出错得多么隐蔽、精妙无比的代码;同时让你无论多牛逼,也写不出多么精彩绝伦、言简意赅的代码。Go 也有这种特质,甚至有些地方比起 Java 更有过之而不及。不信请看:

别人家的写法:

r = f(p1, p2 != null ? p2 : p3)
$r = f($p1, $p2 ?? $p3)

Go 家的写法:

var r someType
if p2 != nil {
r = f(p1, p2)
} else {
r = f(p1, p3)
}

为什么要设计成这样?Go 爸爸说:你们有些人啊,会嵌套很多层 ?:,导致代码可读性太差啦,于是禁止你们使用 ?:,这是家法。在这里,作为熊孩子的代表,我来告诉大家怎样写出让 Go 爸爸无语的代码:

	foo := 1
bar := 2
var foobar int
if foo > bar { if bar > 1 { foobar = 1 } else if bar < 0 { foobar = 2 } else { foobar = 3 } } else { if foo >= 3 { foobar = 4 } else { foobar = 5 } }

怎么样?可读性差不差?

看到了吧,这种傻逼是防不住的,他愿意把 ?: 嵌套好多层,它同样可能会把 if else 嵌套好多层。有素质的人会怎么做?遇到 ?: 嵌套太多立马拆成 if else。所以结论是,即使去掉 ?:,傻逼还是傻逼,但是正常的人写代码就会很啰嗦;支持 ?:,傻逼还是傻逼,正常人用起来爽。要知道一层 ?: 的场景占所有 ?: 场景的比例还是很高的吧。我觉得可以这样,Go 爸爸可以统计一些工业级代码库的 ?: 嵌套层数,作为数据支撑(比如自家 Chrome 里一层 ?: 占 95%,两层占 4.9),然后再在语言层面只支持一层 ?:,编译参数可选打开两层,不支持两层以上。这就功在千秋了。

除了 不支持 ?:,Go 爸爸还有很多这样的设计,随便举几个例子:

  1. 不支持默认参数
  2. 不支持运算符重载
  3. 不提供 goroutine id(以及 gls、可重入锁)

特别是第三点,也是这种思路,因为你们可能会滥用,所以我不提供。类似这种“爸爸思路”,是我今天要喷的最大喷点。前两点也许是抄 Java 的,不怪 Go 爸爸。

综上,Go 爸爸通过扼杀一些基本语法或者一些基础信息,来防止傻逼干坏事,同时让正常人用起来很啰嗦,同时还可能防止不了傻逼干坏事。这跟 Java 通过不提供高级语法来防止傻逼干坏事是师出同门啊,而且他们正好都能写网络服务程序,你说它们像不像?

然而,Go 爸爸也有精分的时候,它居然发明语法糖了耶!比如 if 可以执行一个句句。单就这个语法而言,我的态度是中立偏赞。赞是赞 Go 爸爸确实用过心了,某些时候挺方便,还能缩小变量作用域;不过这个总归是可有可无的,毕竟换一行写也不会死,要变量作用域加个大括号就行。

小语法方面倒是有个亮点,那就是 switch 的隐式 break、显式 fallthrough 处理。不多展开了。

除了防傻逼,Go 爸爸还有一个思路,就是只许州官放火,不许百姓点灯。有两个语法点——

  1. 泛型
  2. 逗号ok断言

先说泛型吧。不支持泛型其实我挺能理解的,因为他确实比 ?: 复杂多了,傻逼用不起,?: 都没有,怎么可能会有泛型呢。然而 Go 爸爸有特权呀,它的 map、chan 可都是泛型的哦。但是你要写一个泛型的语法结构的话,对不起没有。

再说逗号ok断言,同样 Go 爸爸要得起,我们要不起。其实我更想要一个这样的语法:当返回值是 xxx, ok 或者 xxx, err 的时候,我如果用一个返回值接,那么就返回第一个,以便链式调用,同时 !ok 或者 err != nil 的时候 panic。

以上两小点虽然是在喷,不过还好啦。无所谓的。下面讲几个大的方面。

代码组织

我特别赞赏 Go 对于 package 级严格的循环依赖检查。然而如果加上其他规则:

  • 一个目录一个 package
  • 不同路径下的同名目录也是不同 package
  • go 代码无法拆成 .h、.cpp

实际可操作性就会非常差。要拆 package,就要把依赖关系梳理得特别严格,半点不得马虎。这对工一般的程代码来说是个极大的挑战。

我更倾向于做成函数级循环依赖检查,或者不限制(毕竟递归函数也是要支持的嘛)。

这部分,中立偏喷,偏喷是因为 Go 爸爸用了我的小名 internal。

OOP

我特别赞赏 Go 对于 OOP 泛滥成灾的思考与探索,以及对于终结这阵 Java 带来的不正之风的决心。怎么可能万物都是 class 呢。但同时,Go 还是有点矫枉过正的,如果我需要利用传统的 OOP 来搞事情,就非常麻烦,你甚至都无法写出一个框架来。你只能写库让别人用。虽然我也不喜欢框架,但有的时候是需要框架的。

defer 非常切中痛点,特别解决一堆错误 return 外加资源释放的问题。相比之下C 里只能用 goto,C++ 本身不支持但可以玩出 LOKI_ON_BLOCK_EXIT 或者 BOOST_SCOPE_EXIT。defer 一举解决问题。(要是能再增加命名 defer 以及撤销 defer 的功能就更好了。没错,你也许看出来了,我觉得 LOKI_ON_BLOCK_EXIT 是最完美的方案。)

虽然 defer 很好,但不意味着析构就没用武之地了。理想的情况是,析构、多态、defer 都要有……

这部分我的态度是中立。

错误处理

终于要点赞了。错误处理是在我看来 go 完胜的地方,恰到好处地处理问题,又防止滥用。也矫正 Java 带来的歪风邪气。

Java 的设计,让人不得不用异常来处理业务。甚至 Java 自己还帮我们分好类了:一种是不是异常的异常,用来处理业务;另一种是真的异常。一些用惯 Java 的傻逼跑到 C++、PHP、Python 里乱拉屎,到处是 try catch。

Go 爸爸一声令下,万籁俱寂。

goroutine

最后不得不说说 gorouthine,毕竟是卖点嘛。我的态度中立偏赞。赞是因为这是一种太有创意的方案,居然想在在语言层面解决多线程、并发问题;不过我还是觉得这更多的是应用层面的问题,做到官方库里会更好,而不是做成语法。

总结

刚开始用 Go 的时候,特别亮眼,简直处处是亮点,然后越接触越讨厌,一点也不耐看……看得出来,设计者糅合了 C、python、Java 的一些特性,并融入了自己的独特的理解。Go的设计者真的特别特立独行且坚持己见,一些我喜欢的特性因为他们的坚持而存在下来,一些我讨厌的特性也因为他们的坚(Gu)持(Zhi)而不能有所改观。就这样的 Go,想代替 C 作为系统语言,是没戏的;想在网络服务有一番作为,抢 Java 的份额,或许是有机会的,不过最多只能抢 Java 的,连 C# 的都抢不了,C++、PHP 更抢不了。

嗯,除了特定的不得不用的场合,反正我是不会特意用 Go 的。

2019,新年快乐!

Go语言的赞和喷的更多相关文章

  1. NLP系列(4)_朴素贝叶斯实战与进阶

    作者: 寒小阳 && 龙心尘 时间:2016年2月. 出处:http://blog.csdn.net/han_xiaoyang/article/details/50629608 htt ...

  2. NLP系列(4)_朴素贝叶斯实战与进阶(转)

    http://blog.csdn.net/han_xiaoyang/article/details/50629608 作者: 寒小阳 && 龙心尘 时间:2016年2月. 出处:htt ...

  3. Kotlin 的优缺点

    从Android 7.0开始,谷歌使用的API从Oracle JDK切换到了open JDK,这对于谷歌来说是一个艰难的决定.对于开发者来说,却倍感兴奋,这意味着长期的官司问题也许就此结束,Andro ...

  4. 超赞的 Go 语言 INI 文件操作

    灵活的数据源 不光光可以从文件读取配置,还支持 []byte 类型的纯数据读取和基于 io.ReadCloser 的流式读取. 多种格式兼容 各种文件种类的广泛支持,包括但不限于 my.cnf..gi ...

  5. 学习使用C语言/C++编程的7个步骤!超赞~

    C是一种编译性语言.如果你以前从来没有接触过任何的编程语言,那么你则需要学习一下一个拆分的逻辑思维.当我们想要写一个项目或者软件的时候,我们需要把这个整体拆分为7个步骤,这样也会让你的思路看起来更有条 ...

  6. 3行python代码翻译70种语言,这个OCR神奇太赞了

    写在前面的一些P话: 今天给大家介绍一个超级简单且强大的OCR文本识别工具:easyocr. 这个模块支持70多种语言的即用型OCR,包括中文,日文,韩文和泰文等.完全满足了大家对于语言的要求,不管你 ...

  7. 转 - Web新人(偏前端)应该怎样学习(个人观点,勿喷)

    我自己是会计专业,转行自学web的,学习有一两年了,也还是新人一个,只不过不是那种超级“新”的,所以有什么话说得不对,请轻喷.欢迎大家来和我交流. 1.我能不能转行学web? 能不能学web这个不是别 ...

  8. 跨越语言的障碍:C++/CLI 调用 C#

    首先我想投诉一下博客园首页右边栏的广告..最近总是出现很恐怖的整容脸的广告.真的是吓坏了.=.=大家有同感吗? 博客园前一阵子掀起了语言的广泛讨论,事实上语言的争执在整个程序员圈子也没有停止过.以我个 ...

  9. 嵌入式开发中常见3个的C语言技巧

    Hey,大家好!我是CrazyCatJack.今天我来说几个在嵌入式开发中常用的C语言技巧吧.也许你曾经用过,也许你只是见到过但是没有深入理解.那么今天好好补充下吧^_^ 1.指向函数的指针 指针不光 ...

  10. c语言第一章第一节 认识变量

    声明:本人大一新生,闲着无聊..写写c语言教程..菜鸟一枚..大神勿喷!!! 接下来我们都用dev来进行编译..vc++太古老了,没提示功能,不好上手,并且老是出毛病..vs太大了,编个c不至于,运行 ...

随机推荐

  1. 深入剖析Sgementation fault原理

    深入剖析Sgementation fault原理 前言 我们在日常的编程当中,我们很容易遇到的一个程序崩溃的错误就是segmentation fault,在本篇文章当中将主要分析段错误发生的原因! S ...

  2. 【Firefox浏览器】关闭触摸板双指滑动进行前进后退的功能

    痛点 本以为只是Chrome浏览器存在这一奇葩功能,没成想Firefox也沦陷了!有好一阵子在使用Firefox的时候,并未发现其存在这个功能.直到有一天,打开自己的博客,翻阅上篇< [Chro ...

  3. Java开发学习(三十九)----SpringBoot整合mybatis

    一.回顾Spring整合Mybatis Spring 整合 Mybatis 需要定义很多配置类 SpringConfig 配置类 导入 JdbcConfig 配置类 导入 MybatisConfig ...

  4. Java多线程(6):锁与AQS(下)

    您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 之前说过,AQS(抽象队列同步器)是Java锁机制的底层实现.既然它这么优秀,是骡子是马,就拉出来溜溜吧. 首先用重入锁来实现简单的累加,就像这 ...

  5. python中的字符串学习

    # 1.字符串的下标(索引) # 取字符串中的子串 print('1.字符串的下标(索引)') str1 = 'PYTHON' print(str1[0]) print(str1[-4]) # 2.字 ...

  6. JavaWeb2

    1. web服务器软件:Tomcat 1.1 概述 服务器:安装了服务器软件的计算机 服务器软件:接受用户的请求,处理请求,做出响应 web服务器软件:接受用户的请求,处理请求,做出响应 在web服务 ...

  7. select中DISTINCT的应用-过滤表中重复数据

    在表中,一个列可能会包含多个重复值,有时也许希望仅仅列出不同(distinct)的值. DISTINCT 关键词用于返回唯一不同的值. SQL SELECT DISTINCT 语法 SELECT DI ...

  8. AR空间音频能力,打造沉浸式声音体验

    随着元宇宙的兴起,3D虚拟现实广泛引用,让数字化信息和现实世界融合,目前大家的目光主要聚焦于视觉交互层面,为了在虚拟环境中更好的再现真实世界的三维空间体验,引入听觉层面必不可少,空间音频孕育而生. 空 ...

  9. 2022-11-10 Acwing每日一题

    本系列所有题目均为Acwing课的内容,发表博客既是为了学习总结,加深自己的印象,同时也是为了以后回过头来看时,不会感叹虚度光阴罢了,因此如果出现错误,欢迎大家能够指出错误,我会认真改正的.同时也希望 ...

  10. Axios +Vue + themeleay

    1.pom.xml <dependency> <groupId>org.springframework.boot</groupId> <artifactId& ...