
go不会添加一些半生半熟的特性,正交的特性可以结合使用,不像有些语言这个不能和那个一起用,各种特例各种坑
所以它一直没有添加泛型。没有泛型不是优点,半吊子的泛型也不是优点,他们还没发现什么设计可以让泛型完美融入现有的机制而又不需要大动筋骨,所以干脆不做
用惯了泛型再用go,可能会怀念泛型。但用惯了go再用其他语言,会怀念的可能有以下的一种或几种
函数是一等公民,函数可以作为参数传递,可以作为返回值,可以在channel里传递,函数可以引用外部变量构造成closure,命名函数、函数字面量、方法都是同一个kind,不会有函数指针、lambda、Func<Param, Ret>之类的分裂
包管理,用go get <github地址>就能安装一个包或者一个命令,自动下载所有依赖
编译器前端,标准库的go包提供了parser和ast等子包用于处理源码,go/types提供了类型检查,靠这些就可以做出各类工具甚至作为编译器前端(例如编译到llvm的llgo)。这些工具有:
gofmt,代码格式化工具,其实就是将解析得到的ast不做修改直接unparse成代码。也有修改ast后再unparse的,例如这些
gocover,覆盖测试工具,go的覆盖测试比较特别,不是在运行时跟踪调用,而是在各个分支处插入统计代码。插入代码的方式就是修改ast,然后unparse
govet,静态分析工具,分析出对于编译器合法但语义上可能存在bug的代码,也就是个ast walker
oracle,也是源码分析工具,主要是引用分析,这个符号在哪里定义在哪里出现过,这个类型有哪些方法实现了哪些接口等等
golint,代码风格分析,goimports,自动更新imports,等等工具都是用这些机制实现的
go没有官方IDE,但是IDE或者编辑器都可以直接集成这些通用的工具,不用自己实现一套
另外有了ast和类型信息,做基于模版的代码生成不是难题,这类工具已经出现了
go有runtime,可以在运行时提供类型信息,reflect包实现了各种动态操作,获得某个值的类型,构造一个新的值,构造一个复合类型,列举所有方法,根据名字获得方法,动态调用等等,这是不带runtime的语言很难做到的
有runtime也利于debug,各个goroutine的stack trace,代码在哪里分配了内存,分配了多少,活跃的有多少,系统线程是如何利用的等等,都可以方便地获得,不需要做分成debug build, release build等两难全的事
对并发的支持,goroutine和channel这些基础设施没什么好说的了,工具支持才是go的亮点
race detector,goroutine间共享变量的写冲突可以检测到。execution tracer,每个goroutine发生的每个event可以记录下来用于线上分析(类似systemtap、dtrace)
编译速度,google go编译器和标准库总共近70万行go和汇编代码(包括测试代码则是过100万行),从头编译一次,在普通机器上耗时不到2分钟,上个厕所都不够。
