最近又熟悉了下go语言,发现go语言还有许多设计不好的地方,然后又读到了《我为什么放弃Go语言》这篇文章, 对于某些方面,我还是比较认同的。
这篇文章总结了十六点,如下:
- 不支持方法和函数重载(overload)
- 导入pkg的import语句后边部分竟然是文本(import ”fmt”)
- 没有enum类型,全局性常量难以分类,iota把简单的事情复杂化
- 定义对象方法时,receiver类型应该选用指针还是非指针让人纠结
- 定义结构体和接口的语法稍繁,
interface XXX{}
struct YYY{}
不是更简洁吗?前面加上type
关键字显得罗嗦。 - 测试类库testing里面没有AssertEqual函数,标准库的单元测试代码中充斥着
if a != b { t.Fatal(...) }
。 - 语言太简单,以至于不得不放弃很多有用的特性,“保持语言简单”往往成为拒绝改进的理由。
- 标准库的实现总体来说不甚理想,其代码质量大概处于“基本可用”的程度,真正到企业级应用领域,往往就会暴露出诸多不足之处。
- 版本都发展到1.2了,goroutine调度器依旧默认仅使用一个系统线程。GOMAXPROCS的长期存在似乎暗示着官方从来没有足够的信心,让调度器正确安全地运行在多核环境中。这跟Go语言自身以并发为核心的定位有致命的矛盾。(直到2015年下半年1.5发布后才有改观)
- 官方发行版中包含了一个叫oracle的辅助程序,与Oracle数据库毫无关系,却完全无视两者之间的名称混淆。
接着我又看到了许式伟的《Dive into Golang》,里面介绍了很多Go语言的坑,这就 反应了这门语言设计不好的地方,
包括:
1. 切片(slice)的坑,
切片简单地说就是一种很简单的数据结构 struct{ptr, len, cap},ptr表示指向某一个数组的指针(注意:这里是固定长度的数组),len表示当前切片本身保存数据元素的长度,cap表示此切片当前能保存的数据元素容量。不同的切片中的ptr可能指向同一个数组的中的各个元素的地址,因此,在对某个slice做操作的时候,ptr指向数组元素的值发生变化,其他slice的也可以看到。
arr := [6]int{0, 1, 2, 3, 4, 5} slice := arr[1:3] slice2 := slice[1:3] fmt.Println(slice) fmt.Println(slice2) // 结果输出分别为 [1 2] [2 3]
2. 闭包
注意,闭包对原环境都是引用,而不是拷贝值,因此一个闭包运行结果,要依赖于闭包运行那个时刻原环境的值,而不是创建闭包时刻原环境的值。
app := func(in int, out int, args []int) { fmt.Println(in, out, args) } args := []int{1, 2} app2 := func(in int, out int) { app(in, out, args) } args = []int{4, 5} app2(4, 5)
运行结果为 4 5 [4 5]
3. 通道(channel),本质就是一个消息队列,里面会使用到Mutex互斥。
不要使用channel做互斥原子物语,channel可能会有错误,所以读取channel最好使用select操作
王垠对Go语言的 吐槽
有疑问加站长微信联系(非本文作者)