mirror of
https://github.com/chai2010/go2-book.git
synced 2025-06-06 17:53:09 +00:00
commit
c1ab6a4848
12
ch1/ch1-1.md
12
ch1/ch1-1.md
@ -4,7 +4,7 @@ Go1的语法变迁主要从Go第一个正式版本开始,到Go1.10版本截止
|
|||||||
|
|
||||||
### 1.1.1 Go1的诺言
|
### 1.1.1 Go1的诺言
|
||||||
|
|
||||||
Go语言从2007年开始设计,2019年底正式开源,而第一个正式的版本Go1则是在2012年上半年发布。Go1是Go语言官方对整个社区的承诺:Go1之后的版本将保证源代码层面兼容。从Go1的发布日志可以发现,Go1对语言和标准库做了严谨的梳理和完善,正是这次工作才奠定了Go1之后高速发展的十年。
|
Go语言从2007年开始设计,2009年底正式开源,而第一个正式的版本Go1则是在2012年上半年发布。Go1是Go语言官方对整个社区的承诺:Go1之后的版本将保证源代码层面兼容。从Go1的发布日志可以发现,Go1对语言和标准库做了严谨的梳理和完善,正是这次工作才奠定了Go1之后高速发展的十年。
|
||||||
|
|
||||||
Go1的重大变化主要集中在语言和标准库部分。经过多年的发展和普及,大家已经对Go语言目前的标准库非常熟悉了。我们这里主只回顾下Go1的语言变化(包含内置类型和函数)。
|
Go1的重大变化主要集中在语言和标准库部分。经过多年的发展和普及,大家已经对Go语言目前的标准库非常熟悉了。我们这里主只回顾下Go1的语言变化(包含内置类型和函数)。
|
||||||
|
|
||||||
@ -41,9 +41,9 @@ type T1 = T2
|
|||||||
|
|
||||||
类型别名`T1`是通过`=`符号从`T2`定义,这里的`T1`和`T2`是完全相同的类型。
|
类型别名`T1`是通过`=`符号从`T2`定义,这里的`T1`和`T2`是完全相同的类型。
|
||||||
|
|
||||||
Go语言的接口是一大亮点特性,接口是方法的集合,而方法正式依附于类型的函数。而类型别名的一个特殊的地方是,`T1`并不是一个新的类型,因此我们不能再为`T1`定义任何新的方法。
|
Go语言的接口是一大亮点特性,接口是方法的集合,而方法正是依附于类型的函数。而类型别名的一个特殊的地方是,`T1`并不是一个新的类型,因此我们不能再为`T1`定义任何新的方法。
|
||||||
|
|
||||||
之所以引入类型别名,很大的原因是为了解决Go1.7将`context`扩展库移动到标准库带来的问题。因为标准库和扩展库中分别定义了`context.Context`类型,而不同包中的类型是不相容的。而gRPC等很多开源的库最开始以来的是扩展库中的`context.Context`类型,结果导致其无法和Go1.7标准库中的`context.Context`类型兼容。这个问题最终通过类型别名解决了:扩展库中的`context.Context`类型是标准库中`context.Context`的别名类型,从而实现了和标准库的兼容。
|
之所以引入类型别名,很大的原因是为了解决Go1.7将`context`扩展库移动到标准库带来的问题。因为标准库和扩展库中分别定义了`context.Context`类型,而不同包中的类型是不相容的。而gRPC等很多开源的库使用的是最开始以来的扩展库中的`context.Context`类型,结果导致其无法和Go1.7标准库中的`context.Context`类型兼容。这个问题最终通过类型别名解决了:扩展库中的`context.Context`类型是标准库中`context.Context`的别名类型,从而实现了和标准库的兼容。
|
||||||
|
|
||||||
类型别名虽然是为了解决特定问题而引入的补丁特性。但是从类型别名我们可以发现一些有趣的用法:
|
类型别名虽然是为了解决特定问题而引入的补丁特性。但是从类型别名我们可以发现一些有趣的用法:
|
||||||
|
|
||||||
@ -71,7 +71,7 @@ type MakeReaderB interface {
|
|||||||
|
|
||||||
虽然接口定义方法的名字相同,但是方法返回的是两种不同的类型,因此方法的签名是不同的,所以说上面的两个接口并不相同。
|
虽然接口定义方法的名字相同,但是方法返回的是两种不同的类型,因此方法的签名是不同的,所以说上面的两个接口并不相同。
|
||||||
|
|
||||||
我们现在考虑通过类型别名的方式定义一个`ReaderC`,然后定义一个`MakeReaderC`接口:
|
我们现在考虑通过类型别名的方式定义一个`ReaderC`接口,然后定义一个`MakeReaderC`接口:
|
||||||
|
|
||||||
```go
|
```go
|
||||||
type ReaderC = interface {
|
type ReaderC = interface {
|
||||||
@ -82,7 +82,7 @@ type MakeReaderC interface {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
比较神奇的是`MakeReaderC`和`MakeReaderB`接口可能是等价的,因为它定义的方法名字和签名都是相同的。MakeReader方法返回的都是一个匿名的`interface { Read(p []byte) (n int, err error) }`接口类型。而Go语言中,所有的结构相同的匿名类型其实是同一个类型。
|
比较神奇的是`MakeReaderC`和`MakeReaderB`接口可能是等价的,因为它定义的方法名和签名都是相同的。MakeReader方法返回的都是一个匿名的`interface { Read(p []byte) (n int, err error) }`接口类型。而Go语言中,所有的结构相同的匿名类型其实是同一个类型。
|
||||||
|
|
||||||
如果通过类型别名从匿名接口构造接口,就可以避免接口的方法签名被新定义不同接口类型造成断裂的问题(有一点绕口)。
|
如果通过类型别名从匿名接口构造接口,就可以避免造成接口的方法签名被新定义的不同接口类型断裂的问题(有一点绕口)。
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user