作者回复: 👍。说的很好。很认同你提到的基于“类型别名”的渐进式代码修复(Gradual code repair) 思路。这也是类型别名最初被引入go的初衷(https://github.com/golang/proposal/blob/master/design/18130-type-alias.md)。我觉得它也是go面向工程设计哲学的体现。另外type alias在基于现有实现进行扩展并做出新的封装方面也有“奇效”。
作者回复: 好问题! go的组合有多种形式。按你提到的“继承”型组合中,如果组合的两个类型中有相同名字的字段,那怎么解决呢?看下面中的例子: package main type T1 struct { a int } type T2 struct { a int } type T struct { T1 T2 } func main() { var t T // t.a = 5 // 编译报错:ambiguous selector t.a t.T1.a = 5 t.T2.a = 6 println(t.T1.a) // 5 println(t.T2.a) // 6 } 如果T组合的两个类型T1和T2都包含字段a,那么我们不能直接使用t.a,而是通过t.T1.a和t.T2.a分别指代各自类型中的字段a。
作者回复: 罗杰出品的问题,都是精品问题^_^。 先来看第一个问题,Go最初设计目标是通用的系统编程语言,但Go选择支持了GC。Go的GC虽然在go团队的努力下,开销越来越小,但开销小,低延迟不代表没有,这就决定了Go在一些对性能极其敏感的领域可能并不是最好的选择。你的问题中也提到了pvp服务,想必你们也是采用了面向服务的架构,这种架构本身就是可以天然适合技术异构的。如果觉得不妥,也别强求,果断换非GC语言,比如c、c++或是rust。如果说非要坚持用go来完成,那么说明你是go的骨灰粉,在解决问题的过程中,你也会完成一次go技能的升华。 第二个问题,Go语言的简单或者说功能特性少,的确来自与less is more的理念。保持一门小语言,让语言更容易学习与理解。同时每个特性都是经过精心打磨与实现,不能再少了。上周我看了rob pike最新一期的talk,他还在说 “Go语言中变量声明的方式有些多了”,这也是我在实际编码过程中的体会。如果重新来过,我想rob pike会更彻底的执行less is more,将变量声明方式再减少一种。所以说,特性少不是不想做,而是经过深思熟虑,那个特性的确没必要加入到语言中。
作者回复: 从go设计者的初衷来看(https://golang.google.cn/doc/faq#exceptions),go没有采用像java那样的结构化异常处理的确是出于对“简单”原则的考虑。 在java中错误处理与真正的“异常”是混杂在Try-catch机制中的,并没有明显的界限,无论是错误还是异常,一旦throw,方法的调用者就得负责处理它。 但在go中,错误处理与真正的异常处理是严格分开的,也就是说不要将panic掺和到错误处理中。 错误处理是常态,go中只有错误是返回给上层的。一旦出现panic,这意味着整个程序处于即将崩溃的状态,返回给上层几乎也是“无济于事”,所以在go中,一个常见的api设计思路是 不要向外部抛出panic(don't panic!)。如果api中存在panic的可能性,那么api自己要负责处理panic,并通过error将状态返回给上层。如果api无法处理panic,那程序就很大可能是要崩溃了,这种panic多是因为程序bug导致的。
作者回复: 手动点赞
作者回复: 👍
作者回复: 💪
作者回复: 1. 正交(orthogonality)是从几何学中引入的术语,如果两条线以直角相交,如图形上的轴线,就是正交的。如果说两个事物是正交的,那么我们说 这两个事物是独立且解耦的,一个事物的变化不影响另外一个事物。 我们经常用“正交”来评价一个系统的设计,比如在一个设计良好的系统中,数据库代码将与用户界面正交:你可以在不影响数据库的情况下,独>立进行界面的演进。 编程语言的语法元素间也存在着正交的情况,比如文中提到的类型定义与方法是正交的。这意味着一个类型可以有方法,也可以没有方法。而方>法本质上接收类型作为其第一个参数的函数而已(具体参考第24讲)。 在Go语言中,正交的语法还有一些,比如接口就与Go语言其他部分是正交的。 但正交的两个语法特性组合起来可以实现其它特性,这也是我们在一个系统中经常做的事情。 2. 难道不用面向对象就不能复用了么?:) Go有自己的组合的设计哲学,组合也可以实现复用。课程后面会有讲解。
作者回复: 自己总结的。但也依据了go核心团队的一些talk中的内容以及个人对go的理解。
作者回复: 👍