标签 Interface 下的文章

“能力越大,责任越大” – Go语言之父详解将于Go 1.18发布的Go泛型

img{512x368}

注:本文是首发于笔者微信公众号“iamtonybai”上的付费文章,这里免费分享给大家!

在2020.11.9~11.13举行的全球最具影响力的Go语言技术大会GopherCon 2020上,Go语言之父之一的Robert Griesemer为全世界Gopher们带来了本次大会最重量级的演讲“Typing [Generic] Go”

img{512x368}

图:Robert Griesemer带来的有关Go泛型演讲

在这个演讲中,Robert Griesemer向Gopher们介绍了自从今年中旬在Go官网发表文章“The Next Step for Generics”以来Go泛型(Go Generics)技术草案的最新变化,并详细介绍了类型参数(type parameter)是如何满足Go现有的类型系统的,以及Go编译器是如何对Go泛型代码进行类型检查的。

本文整理了此次演讲的重点内容,供广大Gopher参考,希望能为大家理解Go泛型带来帮助。

一. 预备知识

为了更好地理解Robert Griesemer的讲解,这里先带着大家回顾一下Go generics技术草案演化史。

img{512x368}

图:Go泛型技术草案演化时间线

  • 2017年7月,Go核心团队领军人物Russ Cox在Gophercon 2017大会上发表演讲“Toward Go 2”,正式吹响Go向下一个阶段演化的号角;
  • 2018年8月,在Gophercon 2018大会结束后不久,Go核心团队发布了Go2 draft proposal,这里面涵盖了由Ian Lance Taylor和Robert Griesemer操刀主写的Go泛型的第一版draft proposal。这版草案引入了contract关键字来定义泛型类型参数(type parameter)的约束、类型参数放在普通函数参数列表前面的小括号中,并用type关键字声明:
// 第一版泛型技术草案中的典型泛型语法

contract stringer(x T) {
    var s string = x.String()
}

func Stringify(type T stringer)(s []T) (ret []string) {

}
// 简化后的contract语法如下:

contract stringer(T) {
    T String() string
}
  • 2020年6月,《Featherweight Go》论文发表在arxiv.org上,该论文缘于Rob Pike向著名计算机科学家、函数语言专家、Haskell语言的设计者之一、Java泛型的设计者PHILIP WADLER发出的一次邀请,希望PHILIP WADLER帮助Go核心团队解决Go语言的泛型扩展问题:

img{512x368}

图:Rob Pike向PHILIP WADLER发出的邀请

而这篇论文则是对这次邀请的回应。这篇论文为Go语言的一个最小语法子集设计了泛型语法Featherweight Generic Go(FGG),并成功地给出了FGG到Feighterweight Go(FG)的可行性实现的形式化证明。

该篇论文采用monomorphisation(单态)的实现,而非Java使用的擦触法(Erasure),这样的好处之一是如果代码中没有使用任何泛型抽象,程序的运行时不会因支持泛型而承担额外的消耗。

该论文的形式化证明给Go团队带来了信心,也是的Go团队在一些语法问题上达成更广泛的一致。

img{512x368}

图:Robert Griesemer表达了对该论文团队的感谢

  • 2020.6月末,Ian Lance Taylor和Robert Griesemer在Go官方博客发表了文章《The Next Step for Generics》,介绍了Go泛型工作的最新进展。Go团队放弃了之前的技术草案,并重新编写了一个新草案。在这份新技术方案中,Go团队放弃了引入contract关键字作为泛型类型参数的约束,而采用扩展后的interface来替代contract。这样上面的Stringify函数就可以写成如下形式:
type Stringer interface {
    String() string
}

func Stringify(type T Stringer)(s []T) (ret []string) {
    ... ...
}

同时,Go团队还推出了可以在线试验Go泛型语法的playground:https://go2goplay.golang.org,这样gopher们可以直观体验新语法,并给出自己的意见反馈。

  • 2020年11月的GopherCon 2020大会,Griesemer与全世界Gopher同步了Go泛型的最新进展和roadmap,在最新的技术草案版本中,小括号被方括号取代,类型参数前面的type关键字也不再需要了:
func Stringify[T Stringer](s []T) (ret []string) {
    ... ...
}

go2goplay.golang.org也支持了方括号语法,gopher可以在线体验。

下面我们就来看看Griesemer对最新Go泛型技术草案的详细讲解

二. 类型参数(Type parameters)技术草案详解

这版草案与2019年中旬发布的草案的最大变动就是使用interface而不是contract来表达对类型参数的约束

该版设计的主要特性:

  • 类型参数(Type parameters) – 一种将类型或函数进行参数化的机制
  • 约束(Constraints) – 一种表达对类型参数的约束的机制
  • 类型推导(Type inference,可选)

普通函数参数列表 vs. 泛型函数的类型参数列表

我们知道,普通函数的参数列表是这样的:

(x, y aType, z anotherType)
  • x, y, z是形参(parameter)的名字,即变量;
  • aType,anotherType是形参的类型,即类型。

我们再来看一下类型参数(type parameter)列表:

[P, Q aConstraint, R anotherConstraint]
  • P,Q,R是类型形参的名字,即类型;
  • aConstraint,anotherConstraint代表类型参数的约束(constraint),可以理解为一种元类型(meta-type,即修饰类型的类型)。

注:按惯例,类型参数(type parameter)的名字都是头母大写的。

为什么需要类型参数(type parameter)

我们先来看一下当前Go语言标准库中提供的排序方案:

// $GOROOT/src/sort/sort.go
type Interface interface {
        Len() int
        Less(i, j int) bool
        Swap(i, j int)
}

func Sort(data Interface) {
    ... ...
}

为了应用这个排序函数Sort,我们需要让被排序的类型实现sort.Interface接口,就像下面例子中这样:

type IntSlice []int

func (p IntSlice) Len() int           { return len(p) }
func (p IntSlice) Less(i, j int) bool { return p[i] < p[j] }
func (p IntSlice) Swap(i, j int)      { p[i], p[j] = p[j], p[i] }

func main() {
        sl := IntSlice([]int{89, 14, 8, 9, 17, 56, 95, 3})
        fmt.Println(sl)
        sort.Sort(sl)
        fmt.Println(sl)
}

这真是我们想要的实现方式吗?我们真正需要的是这样的:

func Sort(list []Elem)

// 使用
var myList = []Elem{...}
Sort(myList)

解决办法:使用type parameter(类型参数或叫做参数化的类型,将类型作为参数传递):

img{512x368}

图:使用类型参数的Sort

约束(constraints)

约束(constraint)规定了一个类型实参(type argument)必须满足的条件要求。而在泛型Go中,我们使用interface来定义约束

如果某个类型实现了某个约束(规定的所有条件要求),那么它就是一个合法的类型实参。

下面是一个泛型版本的Sort函数:

func Sort[Elem interface{ Less(y Elem) bool }](list []Elem)

我们看到上面函数Sort的类型形参(type parameter)Elem的约束是一个interface,这样传入的类型实参(type argument)只要实现了该接口即可。

约束的定义中也可以引用类型形参,比如下面这个泛型函数:

img{512x368}

图:约束的定义中引用类型形参

类型形参的声明与作用域

img{512x368}

图:类型参数的声明与作用域

类型参数的作用域始于[,终于泛型函数的函数体结尾或泛型类型的声明结尾。

泛型的类型具化与类型检查

下面是一个使用泛型版本Sort函数的例子:

func Sort[Elem interface{ Less(y Elem) bool }](list []Elem)

type book struct{…}
func (x book) Less(y book) bool {…}
var bookshelf []book
…
Sort[book](bookshelf) // 泛型函数调用

上面的泛型函数调用Sort[book](bookshelf)将分成两个阶段:

  1. 具化(instantiation)

形象点说,具化(instantiation)就好比一家生产“排序机器”的工厂根据要排序的对象的类型将这样的机器生产出来的过程。以上面的例子来说,整个具化过程如下:

  • 工厂接单:Sort[book],发现要排序的对象类型为book;
  • 模具检查与匹配:检查book类型是否满足模具的约束要求(即是否实现了Less方法),如满足,则将其作为类型实参替换Sort函数中的类型形参,结果为Sort[book interface{ Less(y book) bool }]
  • 生产机器:将泛型函数Sort具化为一个新函数,这里将其起名为booksort,其函数原型为func([]book)。本质上booksort := Sort[book]
  1. 调用(invocation)

一旦“排序机器”被生产出来,那么它就可以对目标对象进行排序了,这和普通的函数调用没有区别。这里就相当于调用booksort(bookshelf),整个过程只需检查传入的函数实参(bookshelf)的类型与booksort函数原型中的形参类型([]book)是否匹配即可。

用伪代码来表述上面两个过程如下:

Sort[book](bookshelf)

<=>

具化:booksort := Sort[book]
调用:booksort(bookshelf)

泛型类型

除了函数可以携带类型参数变身为“泛型函数”外,类型也可以拥有类型参数而化身为“泛型类型”:

type Lesser[T any] interface{
   Less(y T) bool
}

上面代码中的any代表没有任何约束,等价于interface{}。

泛型类型的类型参数的声明与作用域范围

泛型类型的类型参数的声明方式如下,类型参数的作用域范围也同见下图:

img{512x368}

图:泛型类型的类型参数的声明与作用域

用泛型类型改造Sort

用泛型类型定义一个具名的约束条件- Lesser接口类型:

type Lesser[T any] interface{
   Less(y T) bool
}

使用Lesser[T]作为约束的Sort函数可以这样写:

func Sort[Elem Lesser[Elem]](list []Elem)

注意:任何泛型函数或泛型类型在使用前都必须先“具化(instantiation)”。

我们再来看看Sort函数的内部实现:

func Sort[Elem Lesser[Elem]](list []Elem) {
    ...
    var i, j int
    ...
    if list[i].Less(List[j]) {
        ...
    }
    ...
}
  • 这里的list[i]和list[j]的类型是Elem;
  • Elem不是一个接口类型,它是泛型函数(Sort)的类型参数,Lesser[Elem]是作为类型参数的约束而存在的,不要与函数常规参数列表混淆。

再次强调:类型参数是一个真实的类型,不是一个接口类型(变量),当然我们可以使用一个接口类型作为类型实参来具化一个泛型函数或泛型类型

实参类型自动推导(Argument type inference)

我们是想要:

Sort[book](bookshelf)

还是:

Sort(bookshelf)

显然是后者。我们希望Go编译器能够根据传入的变量自动推导出类型参数的实参类型。

img{512x368}

图:实参类型的自动推导

这样,在具化之前,如果泛型函数调用没有显式提供实参类型,那么Go编译器将进行自动实参类型推导。有了是实参类型的自动推导,大多数泛型调用的方式与常规函数调用一致

类型列表(type lists)

到这里,约束仅限于描述方法要求。下面的函数调用仍然无法工作:

Sort([]int{1, 2, 3})

因为原生的int类型不满足Elem的约束,没有实现Less方法。虽然我们可以用下面替代方法实现整型切片的排序:

type myInt int
func (x myInt) Less(y myInt) bool { return x < y }

但这还是太麻烦了。

Go泛型扩展了interface语法,除了让interface拥有自己的方法列表外,还支持在interface中定义类型列表(type list):

type Float interface {
   type float32, float64
}

// float32和float64都可以作为类型实参传递给Sin
func Sin[T Float](x T) T

现在,一个类型实参要想满足约束,要么它实现了约束中的所有方法,要么它或它的底层类型(underlying type)在约束的类型列表中。

下面是一个泛型函数min的声明与约束定义:

func min[T Ordered](x, y T) T ...

type Ordered interface {
    type int, int8, int16, ..., uint, uint8, uint16, ..., float32, float64, string
}

函数min的实现如下:

func min[T Ordered](x, y T) T {
    if x < y {
        return x
    }
    return y
}
  • x和y的类型都是T,T类型要满足约束Ordered;
  • x < y是合法的,因为在Ordered的类型列表中的每个类型都支持"<"比较。

但不同类型参数代表的却是不同类型:

func invalid[Tx, Ty Ordered](x Tx, y Ty) Tx {
    ...
    if x < y { // 不合法
        ...
    }
}
  • x的类型是Tx,y的类型是Ty;
  • Tx和Ty是不同类型;
  • "<"需要两个操作数拥有相同的类型。

类型列表应用的典型示例

  • 将[]byte和string的操作整合在一起

我们知道目前标准库中有一个bytes包和一个strings包,这两个包一个用于处理[]byte,一个则用于处理string。但使用过这两个包的gopher会发现,这两个包中大部分函数和方法是一样的,甚至处理逻辑都是一样的。有了泛型后,我们可以将对两种类型的大部分操作整合在一起,以Index函数为例:

type Bytes interface {
   type []byte, string
}

// Index returns the index of the first instance of sep
// in s, or -1 if sep is not present in s.
func Index[bytes Bytes](s, sep bytes) int
  • 类型参数(type parameter)之间的关系
type Pointer[T any] interface {
    type *T
}

func f[T any, PT Pointer[T]](x T)

或

func foo[T any, PT interface{type *T}](x T)

上面是基于类型列表表述“一个类型的指针类型”约束的方案。PT的实参的类型必须是T的实参类型的指针类型。

下面这几个函数和接口很大可能会加入到标准库:

func BasicSort[Elem Ordered](list []Elem)

func Sort[Elem Lesser[Elem]](list []Elem)

type Lesser[Elem any] interface {
    Less(Elem) Elem
}

小结

关于泛型声明:

  • 类型参数列表和普通参数列表相似,只是使用"[ ]"括起;
  • 函数和类型都可以拥有类型参数列表;
  • 使用interface表达对类型参数的约束。

关于泛型使用:

  • 泛型函数和类型在使用之前必须先“具化(instantiated)”;
  • 类型自动推导可实现函数隐式具化;
  • 如果类型实参满足约束,那么具化才会合法。

截至2020.10月份的泛型设计草案版本,我们对以下特性设计的满意度为:

img{512x368}

三. 结束语

“能力越大,责任越大”

  • 类型参数(泛型)是Go工具集中的新成员;
  • 它与语言的其他部分正交;
  • 其正交性也打开了编码风格的一个新维度。

泛型引入了抽象,无用的抽象带来复杂性。请三思而后行!

示例1

func ReadAll(r io.Reader) ([]byte, error)

对比:

func ReadAll[reader io.Reader](r reader) ([]byte, error)

=> 引入泛型的版本并未解决任何实际问题(还带来了复杂难以理解的抽象)

示例2

// Drain drains any elements remaining on the channel.
func Drain[T any](c <-chan T)

// Merge merges two channels of some element type into
// a single channel.
func Merge[T any](c1, c2 <-chan T) <-chan T

=> 类型参数让以往无法实现的逻辑成为现实。

何时使用泛型

  • 增强静态类型安全性
  • 更高效的内存使用
  • (显著的)更好的性能

泛型是带有类型检查的宏(macro)。使用宏之前请三思!

接下来的工作

Go核心团队正在着手做出一个完整的泛型实现,以便我们解决所有未解决的问题。我们继续欢迎大家的反馈!

如何抢先体验泛型:

  • playground: https://go2goplay.golang.org/
  • go2go命令工具:git checkout dev.go2go

注:2020.11.21日,Go开发团队技术负责人Russ Cox在golang-dev上的mail确认了Go泛型(type parameter)将在Go 1.18版本落地,即2022.2月份

img{512x368}

关注公众号“iamtonybai”,fgg获取论文“Featherweight Go”下载链接;发送gophercon2020获取GopherCon 2020大会技术ppt资料。

img{512x368}


“Gopher部落”知识星球开球了!高品质首发Go技术文章,“三天”首发阅读权,每年两期Go语言发展现状分析,每天提前1小时阅读到新鲜的Gopher日报,网课、技术专栏、图书内容前瞻,六小时内必答保证等满足你关于Go语言生态的所有需求!星球首开,福利自然是少不了的!2020年年底之前,8.8折(很吉利吧^_^)加入星球,下方图片扫起来吧!

Go技术专栏“改善Go语⾔编程质量的50个有效实践”正在慕课网火热热销中!本专栏主要满足广大gopher关于Go语言进阶的需求,围绕如何写出地道且高质量Go代码给出50条有效实践建议,上线后收到一致好评!欢迎大家订阅!

我的网课“Kubernetes实战:高可用集群搭建、配置、运维与应用”在慕课网热卖中,欢迎小伙伴们订阅学习!

img{512x368}

我爱发短信:企业级短信平台定制开发专家 https://tonybai.com/
smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。2020年4月8日,中国三大电信运营商联合发布《5G消息白皮书》,51短信平台也会全新升级到“51商用消息平台”,全面支持5G RCS消息。

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻)归档仓库 - https://github.com/bigwhite/gopherdaily

我的联系方式:

  • 微博:https://weibo.com/bigwhite20xx
  • 微信公众号:iamtonybai
  • 博客:tonybai.com
  • github: https://github.com/bigwhite

微信赞赏:
img{512x368}

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

2020年Go语言盘点:新冠大流行阻挡不了Go演进的步伐

img{512x368}

2020,这一六十年一遇的庚子年的确“名不虚传”。在这一年发生了很多事,而最受瞩目的事情莫过于新冠疫情的全球大流行。疫情给全球的经济带来了近似毁灭性的打击,给人们的生命带来了极大威胁,给人们的生活也带来了很大痛苦及不确定性。好在这个糟糕的2020年马上就要过去了!相信此时此刻每个人心中都会有一句呐喊:“2020,快滚吧!”。

然而肆虐的新冠疫情并没有阻挡住Go语言前进的坚实步伐。在这艰难的一年中,在Go核心开发团队和Go社区的齐心协力下,Go同样取得了不俗的成绩,甚至在2020年3月(那时Go 1.14版本刚刚发布不到一个月),Go在TIOBE的编程语言排行榜中还一度挤进前十(而2019年同期,Go仅位列18位):

img{512x368}

这恰说明Go语言的开发与推广工作得到了更多来自全球的开发者的认可。在这篇文章中,我们就来做一下2020年Go语言的盘点,看看在2020年围绕Go语言、Go社区和Go生态圈都发生了哪些有影响和有意义的事情。

1. 面对大流行,Go核心团队给出“定心丸”

大流行始于2020年1月的武汉,但真正的全球大流行则大致始于2020年3月。面对新冠全球大流行,Go核心开发团队于3月25日作出反应,在官博发表文章《Go, the Go Community, and the Pandemic》,迅速调整了Go语言2020年的演进计划,给出了大流行期间的工作原则:

  • Go始终排在诸如个人和家庭健康与安全之类的基本问题之后;
  • 调整全年Go技术会议的计划,推迟或改为线上举办虚拟技术大会,为全球Gopher提供获取这些会议最新信息的渠道服务;
  • 为在线培训师、Go职位发布提供便利服务;
  • 为新冠病毒提供帮助工作台:https://covid-oss-help.org/;
  • 调整Go工作计划,缩减Go 1.15中包含的新特性和改进,但会遵循Go 1.15的发布时间表;重点支持gopls、pkg.go.dev的演进和优化。

Go核心开发团队的这份声明虽然简短,但却给Go社区吃了一颗“定心丸”,为Go语言在2020新冠大流行年中的稳步演进确定了节奏,指明了方向,奠定了基础。

2. Go在2020年值得关注的那些变化

2020一年,Go核心开发团队、社区和生态圈做了很多工作,但这里无法一一枚举,仅挑出一些重要的变化列在这里:

  • 2020年2月26日,Go 1.14版本发布。主要的变动点包括:

    • 嵌入接口的方法集可重叠;
    • 基于系统信号机制实现了异步抢占式的goroutine调度;
    • defer性能得以继续优化,理论上有30%的性能提升;
    • go module已经生产就绪,并支持subversion源码仓库;
    • 重新实现了运行时的timer;
    • testing包的T和B类型都增加了自己的Cleanup方法。
  • 2020年4月20日,发布2019年Go开发者调查结果

    • 参与2019开发者调查的gopher数量几乎为2018年的2倍,达到10,975人;
    • 大多数受访者每天都在使用Go,而且这个数字每年都有上升的趋势;
    • Go的使用仍然集中在科技公司,但Go越来越多地出现在更广泛的行业中,如金融和媒体;
    • 调查的大部分指标的同比值都很稳定;
    • 受访者正在使用Go来解决类似的问题,特别是构建API/RPC服务和CLI,和他们工作的组织规模大小关系不大;
    • 大多数团队试图快速更新到最新的Go版本;当第三方供应商迟迟不支持当前的Go版本时,就会给开发者造成采用障碍;
    • 现在Go生态系统中几乎所有人都在使用go module,但围绕包管理的一些混乱仍然存在;
    • 需要改进的高优先级领域包括调试、go module使用以及与云服务交互的体验改善;
    • VS Code和GoLand的使用量持续增加;现在每4个受访者中就有3个首选它们。
  • 2020年6月,vscode-go扩展(vscode上的go标准插件)将主代码库从github.com/microsoft/vscode-go迁移到github.com/golang/vscode-go,成为Go官方项目的一部分。

  • 同在2020年6月,pkg.go.dev网站开源!该网站是Go团队在Go社区建设方面做出的主要工作,开源后的pkg.go.dev将接收更多来自社区的想法和改进意见,比如:11月,pkg.go.dev就发布了新版页面设计原godoc.org的请求也被重定向到pkg.go.dev(广大gopher可能需要一段时间来适应这种改变)。

  • 2020年8月,Go 1.15版本发布,其主要的变动点包括:

    • GOPROXY新增以管道符为分隔符的代理列表值;
    • module cache的存储路径可设置;
    • 改善派生自原生类型的自定义类型变量在panic时的输出形式;
    • 将小整数([0,255])转换为interface类型值时将不会额外分配内存;
    • 加入更现代化的链接器(linker),新链接器的性能要提高20%,内存占用减少30%;
    • 增加tzdata包。
  • 2020年11月初,全球最具影响力的Go语言技术大会GopherCon 2020在线上举行!Austin Clements详细讲解了Go 1.14加入的基于系统信号的抢占式调度器;Go语言之父之一的Robert Griesemer讲解了Go泛型当前的状态以及未来的计划。会后Russ Cox确认了Go团队将在Go 1.18版本中加入Go泛型(类型参数)作为试验特性;

  • 2020年11月10日,Russ Cox代表Go核心开发团队发文庆祝Go语言发布11周年,在文中他回顾了Go这一年来的收获以及对2021年Go 1.16和Go 1.17的展望。文中他还提到了GOPATH的历史使命即将结束,Go将开启全面module-aware模式的Go工具链时代!(下图来自推特):

img{512x368}

  • 2020年12月中旬,Go 1.16beta1发布。在Go 1.16中,Go将原生提供对Apple M1芯片(darwin/arm64)的支持;同时,在Go 1.16中go module将成为默认包依赖管理机制;Go 1.16还提供了支持在Go二进制文件中嵌入静态文件的官方原生方案,支持对init函数的执行时间和内存消耗的跟踪,链接器性能得到进一步优化等。

  • 2020年12月16日,gopls v0.6.0发布。同期,vscode-go也正计划将gopls作为默认语言服务器

3. Go语言当前的状态:已来到“稳定爬升的光明期”

今年笔者在知乎上滞留的时间比往年要长一些,看到很多人问与Go相关的一些问题,大致都是询问有关Go语言前景的,比如:

无论上述问题的题目有何不同,其本质的疑问都是“Go语言前景/钱景如何,值不值得投入去学习?”。那么是否存在一种成熟的方法能相对客观地描会出Go语言的发展态势并能对未来Go的走势做出指导呢?我想Gartner的技术成熟度曲线(The Hype Cycle)或许可以一试。

我们知道Gartner的技术成熟度曲线又叫技术循环曲线,是企业用来评估新科技是否要采用或采用时机的一种可视化方法,它利用时间轴与该技术在市面上的可见度(媒体曝光度)决定要不要采用以及何时该种新科技,下面就是一条典型的技术成熟度曲线的形状:

img{512x368}

同理,将该技术成熟度曲线应用于某种编程语言,比如Go,我们就可以用它来判断该编程语言所处的成熟阶段以辅助决定要不要采用以及何时采用该门语言。我们从知名的TIOBE编程语言指数排行榜获取Go从2009年开源以来至今的指数曲线图,并且根据Go版本发布史在图中标记出了各个时段的Go发布版本:

img{512x368}

对比上面的Gartner成熟度曲线,相信你肯定有所发现。我们共同来解释一下:

  • Go语言从2009年宣布开源以来,经历了两次“高峰”:一次是2009年刚刚宣布开源后,一次是在Go1.7~Go 1.9期间。显然,第一次的高峰实际上是一个“假高峰”,那时的Go连1.0版本都尚未发布,我们完全可以将其“剔除”掉。
  • 从图中来看,Go语言的技术萌芽期是比较长的,从2012年的Go 1.0一直持续到2015年的Go 1.5
  • Go 1.5版本的自举以及Go垃圾回收延迟的大幅下降“引爆”了Go的“媒体曝光度”,Go技术的“期望膨胀期”开始,经历从Go 1.6Go 1.9版本的发布后,业界对Go的期望达到了峰值;
  • 从Go 1.10开始,Go似乎变得“仿徨”起来,原本期望Go“一统天下”的愿望没能实现,全面出击失败后,期望的落空导致了人们对Go产生了“功能孱弱劣势”的印象,于是Go在Go 1.11发布前跌到了“泡沫破裂”的谷底;
  • Go 1.11引入了Go module,给社区解决Go包依赖问题打了一剂强心剂,于是Go又开始了缓慢的爬升;
  • 从TIOBE提供的曲线来看,Go 1.12Go 1.15版本的发布让我们有信心认为Go已经进入了“稳步爬升的光明期”。

到此,我相信知乎上的很多问题都应该迎刃而解了,剩下的只是如何学习Go的细节如何Go进阶了。

不过可能还有很多朋友会问,Go何时能达到实质生产高峰期呢?这个问题真不好回答。但进入了“稳步爬升的光明期”后的Go到达实质生产高峰期只是一个时间问题了,也许2022年初发布的支持Go泛型特性的Go 1.18版本会快速推动Go向更高阶段进发!

4. 展望Go的2021:继续蓄力,迎接下一个“引爆点”

促使Go回到“稳步爬升光明期”的go module机制将在2021年年初正式发布的Go 1.16中成为默认包依赖管理机制。而Go 1.16版本也已经处于特性冻结并发布了beta1版本的阶段,其更多特性可以参考我的“Go 1.16新功能特性不完全前瞻”一文。

将于2021年八月发布的Go 1.17的里程碑已经建立, 从里程碑的内容来看,已基本确定加入的功能特性和改进包括:

当然Go 1.17还会持续优化链接器,更多功能特性和改进还待Go团队策划补充。

而万众期待的Go泛型依然会继续打磨,从2016年Ian Lance Taylor提出“Go should have generics”的设计草案以来,Go泛型草案至今已经讨论了4年多了,这再次证明了Go团队对于这类会显著增加Go复杂性的特性是多么地“慎之又慎”。虽然Go团队初步确定了在Go 1.18版本中将Go泛型(类型参数)落地,但近期Go项目中关于Go泛型的主issue:proposal: spec: generic programming facilities中仍然有不少反对的声音。Go团队在“继续保持Go简单”的道路上真是任重道远啊!

总之,2021年,Go将继续稳步爬升,也许爬的并没有那么快,但在我看来,这是在积蓄力量,等待着下一个引爆点。

5. 小结

Go在新冠疫情大流行的历史时期依旧步行稳健,为下一个“引爆点”积极蓄力。Go在自己传统领域依旧存在明显优势,比如:企业级应用、基础设施、中间件、微服务API、命令行应用等,并且在这些领域取得了越来越多开发者的青睐。

Go在其他领域也有“意外收获”,比如:在黑客工具领域,Go已经逐渐威胁着Python的龙头地位了,显然语法简单原生并发自带“电池”、轻松跨平台的编译以及编译为独立二进制文件的Go与黑客的需求十分契合。不过,在安全领域成为了进攻“武器”,这想必是Go设计者们所意料不到的。

6. 福利!2020年本博客最受欢迎Go相关文章TOP10


Gopher部落知识星球已正式转正了!高品质首发Go技术文章,“三天”首发阅读权,每年两期Go语言发展现状分析,每天提前1小时阅读到新鲜的Gopher日报,网课、技术专栏、图书内容前瞻,六小时内必答保证等满足你关于Go语言生态的所有需求!星球首开,福利自然是少不了的!2020年年底之前,8.8折加入星球,下方图片扫起来吧,先到先得哦!

Go技术专栏“改善Go语⾔编程质量的50个有效实践”正在慕课网火热热销中!本专栏主要满足广大gopher关于Go语言进阶的需求,围绕如何写出地道且高质量Go代码给出50条有效实践建议,上线后收到一致好评!欢迎大家订阅!

我的网课“Kubernetes实战:高可用集群搭建、配置、运维与应用”在慕课网热卖中,欢迎小伙伴们订阅学习!

img{512x368}

我爱发短信:企业级短信平台定制开发专家 https://tonybai.com/
smspush : 可部署在企业内部的定制化短信平台,三网覆盖,不惧大并发接入,可定制扩展; 短信内容你来定,不再受约束, 接口丰富,支持长短信,签名可选。

2020年4月8日,中国三大电信运营商联合发布《5G消息白皮书》,51短信平台也会全新升级到“51商用消息平台”,全面支持5G RCS消息。

著名云主机服务厂商DigitalOcean发布最新的主机计划,入门级Droplet配置升级为:1 core CPU、1G内存、25G高速SSD,价格5$/月。有使用DigitalOcean需求的朋友,可以打开这个链接地址:https://m.do.co/c/bff6eed92687 开启你的DO主机之路。

Gopher Daily(Gopher每日新闻)归档仓库 – https://github.com/bigwhite/gopherdaily

我的联系方式:

  • 微博:https://weibo.com/bigwhite20xx
  • 微信公众号:iamtonybai
  • 博客:tonybai.com
  • github: https://github.com/bigwhite
  • “Gopher部落”知识星球:https://public.zsxq.com/groups/51284458844544

微信赞赏:
img{512x368}

商务合作方式:撰稿、出书、培训、在线课程、合伙创业、咨询、广告合作。

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 商务合作请联系bigwhite.cn AT aliyun.com

欢迎使用邮件订阅我的博客

输入邮箱订阅本站,只要有新文章发布,就会第一时间发送邮件通知你哦!

这里是 Tony Bai的个人Blog,欢迎访问、订阅和留言! 订阅Feed请点击上面图片

如果您觉得这里的文章对您有帮助,请扫描上方二维码进行捐赠 ,加油后的Tony Bai将会为您呈现更多精彩的文章,谢谢!

如果您希望通过微信捐赠,请用微信客户端扫描下方赞赏码:

如果您希望通过比特币或以太币捐赠,可以扫描下方二维码:

比特币:

以太币:

如果您喜欢通过微信浏览本站内容,可以扫描下方二维码,订阅本站官方微信订阅号“iamtonybai”;点击二维码,可直达本人官方微博主页^_^:
本站Powered by Digital Ocean VPS。
选择Digital Ocean VPS主机,即可获得10美元现金充值,可 免费使用两个月哟! 著名主机提供商Linode 10$优惠码:linode10,在 这里注册即可免费获 得。阿里云推荐码: 1WFZ0V立享9折!


View Tony Bai's profile on LinkedIn
DigitalOcean Referral Badge

文章

评论

  • 正在加载...

分类

标签

归档



View My Stats