共计 2111 个字符,预计需要花费 6 分钟才能阅读完成。
—Tony Bai · Go 语言第一课
设计哲学之于编程语言,就好比一个人的价值观之于这个人的行为。
Go 语言的设计哲学总结为五点:简略、显式、组合、并发和面向工程。
简略
Go 语法层面:
- 仅有 25 个关键字,支流编程语言起码
- 内置垃圾收集,升高开发人员内存治理的心智累赘;
- 首字母大小写决定可见性,无需通过额定关键字润饰;
- 变量初始为类型零值,防止以随机值作为初值的问题;
- 内置数组边界查看,极大缩小越界拜访带来的安全隐患;
- 内置并发反对,简化并发程序设计;
- 内置接口类型,为组合的设计哲学奠定根底;
- 原生提供欠缺的工具链,开箱即用;
简略的设计哲学是 Go 生产力的源泉.
显式
package main
import "fmt"
func main() {
var a int16 = 5
var b int = 8
var c int64
c = a + b
fmt.Printf("%d\n", c)
}
如果咱们编译这段程序,将失去相似这样的编译器谬误:“invalid operation: a + b
(mismatched types int16 and int)”。咱们能看到 Go 与 C 语言的隐式主动类型转换不
同,Go 不容许不同类型的整型变量进行混合计算,它同样也不会对其进行隐式的主动转
换。
在 Go 语言中,不同类型变量是不能在一起进行混合计算的,这是因为 Go 心愿开发人员
明确晓得本人在做什么.
组合
Go 推崇的是组合的设计哲学.
- Go 语言无类型档次体系,各类型之间是互相独立的,没有子类型的概念;
- 每个类型都能够有本人的办法汇合,类型定义与办法实现是正交独立的;
- 实现某个接口时,无需像 Java 那样采纳特定关键字润饰;
- 包之间是绝对独立的,没有子包的概念。
Go 语言其实是为咱们出现了这样的一幅图景:一座座没有关联的“孤岛”,但每个岛内又都很精彩。那么当初摆在面前的工作,就是在这些孤岛之间以最适当的形式建设关联,并造成一个整体。而 Go 抉择采纳的组合形式,也是最次要的形式.
Go 语言为撑持组合的设计提供了类型嵌入(Type Embedding)。通过类型嵌入,咱们可
以将曾经实现的性能嵌入到新类型中,以疾速满足新类型的性能需要.
被嵌入的类型和新类型两者之间没有任何关系,甚至互相齐全不晓得对方的存在,更没有
经典面向对象语言中的那种父类、子类的关系,以及向上、向下转型(Type Casting)。
通过新类型实例调用办法时,办法的匹配次要取决于办法名字,而不是类型。这种组合方
式,我称之为垂直组合,即通过类型嵌入,疾速让一个新类型“复用”其余类型曾经实现
的能力,实现性能的垂直扩大。
你能够看看上面这个 Go 规范库中的一段应用类型嵌入的组合形式的代码段。
// $GOROOT/src/sync/pool.go
type poolLocal struct {private interface{}
shared []interface{}
Mutex
pad [128]byte
}
在代码段中,咱们在 poolLocal 这个构造体类型中嵌入了类型 Mutex,这就使得
poolLocal 这个类型具备了互斥同步的能力,咱们能够通过 poolLocal 类型的变量,间接
调用 Mutex 类型的办法 Lock 或 Unlock。
咱们在规范库中还会常常看到相似如下定义接口类型的代码段:
type ReadWriter interface {
Reader
Writer
}
这里,规范库通过嵌入接口类型的形式来实现接口行为的聚合,组成大接口,这种形式在
规范库中尤为罕用,并且曾经成为了 Go 语言的一种习用法。
垂直组合实质上是一种“能力继承”,采纳嵌入形式定义的新类型继承了嵌入类型的能
力。Go 还有一种常见的组合形式,叫程度组合。和垂直组合的能力继承不同,程度组合是
一种能力委托(Delegate),咱们通常应用接口类型来实现程度组合。
比方一种常见办法就是,通过承受接口类型参数的一般函数进行
组合,如以下代码段所示:
// $GOROOT/src/io/ioutil/ioutil.go
func ReadAll(r io.Reader)([]byte, error)
// $GOROOT/src/io/io.go
func Copy(dst Writer, src Reader)(written int64, err error)
函数 ReadAll 通过 io.Reader 这个接口,将 io.Reader 的实现与 ReadAll 所在
的包低耦合地程度组合在一起了,从而达到从任意实现 io.Reader 的数据源读取所有数据
的目标。
并发
Go 放弃了传统的基于操作系统线程的并发模型,而采纳了用户层轻量级线程,Go 将之称为 goroutine。
goroutine 占用的资源十分小,Go 运行时默认为每个 goroutine 调配的栈空间仅 2KB。
goroutine 调度的切换也不必陷入(trap)操作系统内核层实现,代价很低。因而,一个
Go 程序中能够创立成千上万个并发的 goroutine。而且,所有的 Go 代码都在 goroutine
中执行,哪怕是 go 运行时的代码也不例外。
面向工程
Go 语言设计的初衷,就是面向解决真实世界中 Google 外部大规模软件开发存在的各种
问题,为这些问题提供答案,这些问题包含:程序构建慢、依赖治理失控、代码难于理
解、跨语言构建难等。