1
0
mirror of https://github.com/chai2010/go2-book.git synced 2025-06-04 08:08:25 +00:00
This commit is contained in:
chai2010 2019-02-25 11:48:21 +08:00
parent af8f033b45
commit f13f21d387
8 changed files with 120 additions and 90 deletions

View File

@ -1,4 +1,9 @@
# 目录
* [第1章 语法糖变迁](ch1/readme.md)
* [1.1 Go1的语法变迁](ch1/ch1-1.md)
* [第1章 语法变迁](ch1/readme.md)
* [1.1 Go1的诺言](ch1/ch1-1.md)
* [1.2 Go1到Go1.10](ch1/ch1-2.md)
* [1.3 Go1.10过渡到Go2](ch1/ch1-3.md)
* [1.4 Go2诞生](ch1/ch1-4.md)
* [第2章 模块化](ch2/readme.md)
* [第3章 错误处理](ch3/readme.md)

View File

@ -1,88 +1,8 @@
## 1.1 Go1的语法变迁
# 1.1 Go1的诺言
Go1的语法变迁主要从Go第一个正式版本开始到Go1.10版本截止。最大的变化其实是在Go1发布时就已经完成了而Go1到Go1.10期间仅仅增加了极少数的变动
Go语言从2007年开始设计2009年底正式开源而第一个正式的版本Go1则是在2012年上半年发布。Go1的语法变迁主要从Go第一个正式版本开始Go1是Go语言官方对整个社区的承诺Go1之后的版本将保证源代码层面兼容
### 1.1.1 Go1的诺言
从Go1的发布日志可以发现Go1对语言和标准库做了严谨的梳理和完善Go1的重大变化主要集中在语言和标准库部分。其中语言部分最大的变化是将原先的`os.Error`接口用内置的`error`接口类型替代、内置函数引入了`close`函数用户管道的关闭操作。此外,还对加强了`init``append`内置函数增强了复合类型字面值的支持针对Unicode字符增加了`rune`别名改善了对map的遍历和删除元素操作改进了影子返回值的报警提示复制结构体时涵盖未导出的成员明确了哪些类型可以进行相等性测试。同时对每个标准库的路径和功能进行详细的设计和完善。
Go语言从2007年开始设计2009年底正式开源而第一个正式的版本Go1则是在2012年上半年发布。Go1是Go语言官方对整个社区的承诺Go1之后的版本将保证源代码层面兼容。从Go1的发布日志可以发现Go1对语言和标准库做了严谨的梳理和完善正是这次工作才奠定了Go1之后高速发展的十年。
Go1的重大变化主要集中在语言和标准库部分。经过多年的发展和普及大家已经对Go语言目前的标准库非常熟悉了。我们这里主只回顾下Go1的语言变化包含内置类型和函数
https://golang.org/doc/go1#language
### 1.1.2 Go1到Go1.10
#### Go1.2
https://golang.org/doc/go1.2#language
#### Go1.4
https://golang.org/doc/go1.4#language
#### Go1.5
https://golang.org/doc/go1.5#language
#### Go1.8
https://golang.org/doc/go1.8#language
#### Go1.9
Go1.9终于引入了类型别名的特性。类型别名的特性如下:
```go
type T1 = T2
```
类型别名`T1`是通过`=`符号从`T2`定义,这里的`T1``T2`是完全相同的类型。
Go语言的接口是一大亮点特性接口是方法的集合而方法正是依附于类型的函数。而类型别名的一个特殊的地方是`T1`并不是一个新的类型,因此我们不能再为`T1`定义任何新的方法。
之所以引入类型别名很大的原因是为了解决Go1.7将`context`扩展库移动到标准库带来的问题。因为标准库和扩展库中分别定义了`context.Context`类型而不同包中的类型是不相容的。而gRPC等很多开源的库使用的是最开始以来的扩展库中的`context.Context`类型结果导致其无法和Go1.7标准库中的`context.Context`类型兼容。这个问题最终通过类型别名解决了:扩展库中的`context.Context`类型是标准库中`context.Context`的别名类型,从而实现了和标准库的兼容。
类型别名虽然是为了解决特定问题而引入的补丁特性。但是从类型别名我们可以发现一些有趣的用法:
```go
type ReaderA interface {
Read(p []byte) (n int, err error)
}
type ReaderB = interface {
Read(p []byte) (n int, err error)
}
```
上面定义的两个读接口都有同样的方法集合。而Go语言的接口是采用隐式的转义因此可能有人会觉得这两种写法根本没有什么意义
但是接口本身也是一种类型,如果我们基于`ReaderA``ReaderB`类型继续构造新的方法,就产生了差异:
```go
type MakeReaderA interface {
MakeReader() ReaderA
}
type MakeReaderB interface {
MakeReader() ReaderB
}
```
虽然接口定义方法的名字相同,但是方法返回的是两种不同的类型,因此方法的签名是不同的,所以说上面的两个接口并不相同。
我们现在考虑通过类型别名的方式定义一个`ReaderC`接口,然后定义一个`MakeReaderC`接口:
```go
type ReaderC = interface {
Read(p []byte) (n int, err error)
}
type MakeReaderC interface {
MakeReader() ReaderC
}
```
比较神奇的是`MakeReaderC``MakeReaderB`接口可能是等价的因为它定义的方法名和签名都是相同的。MakeReader方法返回的都是一个匿名的`interface { Read(p []byte) (n int, err error) }`接口类型。而Go语言中所有的结构相同的匿名类型其实是同一个类型。
如果通过类型别名从匿名接口构造接口,就可以避免新定义的不同接口类型对接口的方法签名造成影响。
经过多年的发展和普及大家已经对Go1语言和标准库已经耳熟能详对变更的细节就不详细展开了。但正是这次梳理工作才奠定了Go1之后高速发展的十年。

View File

@ -1,3 +1,100 @@
## Go1到Go2过渡期的语法变迁
# 1.2 Go1到Go1.10
因为Go1承诺Go1后序的版本都保持了向前兼容的目标。不过在从Go1发展到Go1.10的过程中语言依然是增加了一些新的特性。本节我们简单回顾Go1到Go1.10的变化。
## 1.2.1 Go1.2
Go1.2最大的语言变化是切片操作时可以设置新切片的容量。这个需求在Go1之前就被提出了但是因为Go1修改工作较大而延期到了Go1.2才被实现。
比如下面的代码:
```go
var a = make([]int, 10)
var b = a[i:j:k]
```
其中`b`切片是从`a`切片的第`i`个元素开始到第`j`个元素前结束,`b`切片的容量为`k``k`指定的容量不能超出`a`切片的容量)。
为了配合切片语法的变更,`reflect`包也增加了相应的方法:
```
func (v Value) SetCap(cap int)
func (v Value) Slice3(low, high, max int) Value
```
其中`Value.SetCap`只调整切片的容量,和`a[::cap]`写法效果等价。而`Value.Slice3`在进行切片操作的同时也指定新切片的容量,和`a[low:high:max]`写法效果等价。
通过限制子切片的容量,可以将不同子切片进行安全的分割,避免子切片无意越界操作其它切片空间。
## 1.2.2 Go1.4
https://golang.org/doc/go1.4#language
## 1.2.3 Go1.5
https://golang.org/doc/go1.5#language
## 1.2.4 Go1.7
https://golang.org/doc/go1.7#context
## 1.2.5 Go1.8
https://golang.org/doc/go1.8#language
## 1.2.6 Go1.9
Go1.9终于引入了类型别名的特性。类型别名的特性如下:
```go
type T1 = T2
```
类型别名`T1`是通过`=`符号从`T2`定义,这里的`T1``T2`是完全相同的类型。
Go语言的接口是一大亮点特性接口是方法的集合而方法正是依附于类型的函数。而类型别名的一个特殊的地方是`T1`并不是一个新的类型,因此我们不能再为`T1`定义任何新的方法。
之所以引入类型别名很大的原因是为了解决Go1.7将`context`扩展库移动到标准库带来的问题。因为标准库和扩展库中分别定义了`context.Context`类型而不同包中的类型是不相容的。而gRPC等很多开源的库使用的是最开始以来的扩展库中的`context.Context`类型结果导致其无法和Go1.7标准库中的`context.Context`类型兼容。这个问题最终通过类型别名解决了:扩展库中的`context.Context`类型是标准库中`context.Context`的别名类型,从而实现了和标准库的兼容。
类型别名虽然是为了解决特定问题而引入的补丁特性。但是从类型别名我们可以发现一些有趣的用法:
```go
type ReaderA interface {
Read(p []byte) (n int, err error)
}
type ReaderB = interface {
Read(p []byte) (n int, err error)
}
```
上面定义的两个读接口都有同样的方法集合。而Go语言的接口是采用隐式的转义因此可能有人会觉得这两种写法根本没有什么意义
但是接口本身也是一种类型,如果我们基于`ReaderA``ReaderB`类型继续构造新的方法,就产生了差异:
```go
type MakeReaderA interface {
MakeReader() ReaderA
}
type MakeReaderB interface {
MakeReader() ReaderB
}
```
虽然接口定义方法的名字相同,但是方法返回的是两种不同的类型,因此方法的签名是不同的,所以说上面的两个接口并不相同。
我们现在考虑通过类型别名的方式定义一个`ReaderC`接口,然后定义一个`MakeReaderC`接口:
```go
type ReaderC = interface {
Read(p []byte) (n int, err error)
}
type MakeReaderC interface {
MakeReader() ReaderC
}
```
比较神奇的是`MakeReaderC``MakeReaderB`接口可能是等价的因为它定义的方法名和签名都是相同的。MakeReader方法返回的都是一个匿名的`interface { Read(p []byte) (n int, err error) }`接口类型。而Go语言中所有的结构相同的匿名类型其实是同一个类型。
如果通过类型别名从匿名接口构造接口,就可以避免新定义的不同接口类型对接口的方法签名造成影响。
TODO

5
ch1/ch1-3.md Normal file
View File

@ -0,0 +1,5 @@
# 1.3 Go1.10过渡到Go2
<!--
删除二进制包
-->

1
ch1/ch1-4.md Normal file
View File

@ -0,0 +1 @@
# 1.4 Go2诞生

View File

@ -1,4 +1,4 @@
# 第1章 语法变迁
# 第1章 语法变迁
Go语言语法变化非常少主要发生在Go1.10之前。Go1.10主要的开发工作在2017年下半年完成在2018年初正式发布。Go1.10版可以说是Go1和Go2的分水岭虽然语言本身没有大的变化但是Go语言官方正式开始准备Go2的前期设计工作。在Go1.10以前很多关于语言细节修改的建议绝大部分都被冻结了。但是在Go1.10以后语言改进的工作又重新纳入日程。本章重点回顾Go1.0发布以来,语言发生了哪些细微的变化。
Go语言语法变化非常少主要发生在Go1.10之前。Go1.10主要的开发工作在2017年下半年完成在2018年初正式发布。Go1.10版可以说是Go1和Go2的分水岭虽然语言本身没有大的变化但是Go语言官方正式开始准备Go2的前期设计工作。在Go1.10以前很多关于语言细节修改的建议绝大部分都被冻结了。但是在Go1.10以后语言改进的工作又重新纳入日程。本章重点回顾Go1.0发布以来,语言发生了哪些细微的变化。

1
ch2/readme.md Normal file
View File

@ -0,0 +1 @@
# 第2章 模块化

1
ch3/readme.md Normal file
View File

@ -0,0 +1 @@
# 第3章 错误处理