music unfamous original game design efficient software wtf
life ui algorithm fix programming

《为什么Go是一种设计糟糕的编程语言》之浅见

作者:frinity  Golang    2016-12-1  标签:  programming 

在网上闲逛,发现这篇文章《为什么Go是一种设计糟糕的编程语言》 是一篇翻译来的文章,原文也没去看,主要代码就在那放着。显然,这是一个 Golang 的拥趸在搔首弄姿。发了自己调试 Bug 的牢骚,而且赚赚眼球,隔空叫喊 Rob Pike,Rob Pike 说了,对我喊话的多了,你算老节?

下面针对该文原作者提出的几个糟点发表一点看法

1,Slice 操作不对

作者在进行插入操作,其实我们知道 Slice 在底层是 Array,Array 在底层高度类似 C 的数组,这种类型的插入每一次都会移动元素,恶劣的会重新申请内存,然后移动元素。插入一个元素的空间复杂度,时间复杂度都比较高,在 C 中 插入,删除比较多的操作应该用动态链表这种存储结构 。
退一步说,即使铁了头就用 Slice,作者毕竟也实现了,没有错误。

2,Nil 接口不总是 nil

看了作者的代码,其实把我们带到了一个误区,第 16 行 其实返回了一个指向 MagicError 的指针,只不过这个指针是 nil ,但还是一个指针类型。 下面给出一个修正的代码可以感受到作者满满的恶意:

package main

import "fmt"

type MagicError struct{}

func (MagicError) Error() string {
	return "[Magic]"
}

func Generate() *MagicError {
	return nil
}

func Test() error {
	var p *MagicError = Generate()
	if p != nil {
		return p
	}
	return nil
}

func main() {
	var e error = Test()
	if e != nil {
		fmt.Println("Hello, Mr. Pike!")
	}
}

这里Go 不同于 C,C 里面能和 0 值比较的有很多类型,Go 有 Type Base ,类似于其他语言的 Object,Go 是 Interface,但又不同于 Object,这是作者不明白底层模型之下的一种想当然。

3,可笑的变量覆盖

如果说第2条是作者耍的花招,那么第三条简直就是耍无赖了,看 gcc 的

#include <stdio.h>

int Secret(){
	return 42;
}

int main()
{
	int number=0;
	printf("before:%d\n",number);

	{
		int number = Secret();
		printf("inside:%d\n",number);
	}
	printf("after:%d\n",number);
}

你会惊奇的发现 C 的结果和 Golang 一样。 再来看看 Python 代码

#!/usr/bin/python
# -*- coding: utf-8 -*-

def secret():
	return 42

number=0
print "before:",number

if(True):
	number=secret()
	print "inside:",number
print "after:",number
显然,这是作者想要的结果,作者也被验明是 Python 出身。 高层语言让人不懂底层,这是该语言的优势,怕的就是你先学了上层的语言,然后去下面溜达。由奢入俭难啊。

4,不能把 []struct 当成 []interface 传递

到了第4点,作者表现出了耍花招的极高天分和混淆视听的深厚功底。 在C++中,往往用父类指针调用子类的虚函数实现。但对于数组,在C++中这同样是不可行的,Java 也不可行, interface 传递 struct 和 []interface 传递 []struct 是两个概念,后者是两种不同的类型--基于 Slice 的类型,而不是什么接口。就这么简单。作者说了接口半天的不是,却拿 Slice 来举例子,从哪开始喷你呢?不一个频道啊。

但是,这确实是个问题;作者对于这个问题的解决方案应该是正确的。(编程到这一步,你应该闻到一些坏味道)

5,不起眼的 range 循环

 这逻辑就简单多了。作者自己也说了:这不是问题(他对这个问题还是比较有感觉的),归结于 range 太不起眼,自己默默的调试好代码扇自己几巴掌就行了,就别再出来丢人了。

foreach($k as $v){
  $v = 2* $v;
}
像这段 PHP 代码,我当初运行没有达到目的,我会说?这语句够隐晦了吧?况且一般人他想不到PHP里还能 &。

6,编译器严谨性

不是喜欢 Python么?去看看 Python ,不鼓励逗号分号,甚至括号,但列表里也用了逗号,只有一个元素还必须跟个逗号! set=(2,)

结论就是列表元素必须有个分隔符,否则,一个数字列表你知道从哪断开?一次存1块存5次,取出来11111块,想法是好的,我懂。

7,Go generator 太诡异了

其实,你想想,世界上整个软件系统一直在运行,杂七杂八的设备,杂七杂八的规范,杂七杂八的人员,它一直在运行,Go generator 算什么

作者说了半天,也就 import 这个老梗值得一喷再喷。