新闻资讯  快讯  焦点  财经  政策  社会
互 联 网   电商  金融  数据  计算  技巧
生活百科  科技  职场  健康  法律  汽车
手机百科  知识  软件  修理  测评  微信
软件技术  应用  系统  图像  视频  经验
硬件技术  知识  技术  测评  选购  维修
网络技术  硬件  软件  设置  安全  技术
程序开发  语言  移动  数据  开源  百科
安全防护  资讯  黑客  木马  病毒  移动
站长技术  搜索  SEO  推广  媒体  移动
财经百科  股票  知识  理财  财务  金融
教育考试  育儿  小学  高考  考研  留学
您当前的位置:首页 > IT百科 > 程序开发 > 语言 > Go语言

Go语言回顾:从Go 1.0到Go 1.13

时间:2019-09-11 13:16:32  来源:  作者:

Go 1.13版本在2019.9.3正式发布!国外的Gopher Vincent Blanchon发表了一篇文章《Go: Retrospective》(科学上网阅读),对Go从1.0版本到1.13版本做了简要的回顾,这里是那篇文章的译文。

<a href=http://www.solves.com.cn/it/cxkf/yy/go/ target=_blank class=infotextkey>Go语言</a>回顾:从Go 1.0到Go 1.13

 

对于每一位Go开发者来说,Go语言的演化历程是必须要知道的事情。了解这些横跨年份发布的大版本的主要变化将有助于Gopher理解Go语言的发展理念以及该语言每个版本的优势与不足。更多关于特定版本的变更细节,可以参考每个版本对应的Changelog。

Go 1.0 – 2012.3月

伴随着Go语言的第一个版本,Go的缔造者还发布了一份兼容性文档。该文档保证未来的Go版本将保持向后兼容性(backward-compatible),即始终兼容已有的代码,保证已有代码在Go新版本下编译和运行的正确性。

Go 1.0版本还包含了go tool pprof命令,这是一个Google pprof C++ profiler的变体。Go 1.0还提供了go vet命令(之前的go tool vet),用于报告Go package中可能的错误。

Go 1.1 – 2013.5月

该版本主要专注于语言改善和性能提升(编译器、垃圾回收、map、goroutine调度)。这里是一个改善后的效果示意图:

Go语言回顾:从Go 1.0到Go 1.13

 

图来自https://dave.cheney.net/2013/05/21/go-11-performance-improvements

这个版本同时还嵌入了一个竞态探测器(race detector),这个工具对于Go这种原生并发的语言是十分必要的。在《Race Detector with ThreadSanitizer”》一文中,你可以找到有关race detector的更多详细信息。

在这个版本中的一个重点变动是Goroutine调度器被重写了,重写后的调度器性能大幅提升。

重写后的Go调度器的设计如下图:

Go语言回顾:从Go 1.0到Go 1.13

 

图来自 https://rakyll.org/scheduler/

M对应的是操作系统的线程。P表示一个处理器(P的数量不能超过GOMAXPROCS),每个P拥有一个本地goroutine队列。在1.1版本之前,P这个抽象并不存在。所有goroutine的调度通过全局互斥锁进行全局级别的管理。这次改进实现了”work-stealing”算法,允许某个P从其他P的队列中”偷goroutine”:

Go语言回顾:从Go 1.0到Go 1.13

 

图来自 https://rakyll.org/scheduler/

更多关于Go调度器调度原理以及”work-stealing”算法的信息,可以查看Jaana B. Dogan的文章《Go’s work-stealing scheduler》。

Go 1.2 – 2013.12

在该版本中,Go test命令开始支持代码测试覆盖率统计了,并且通过go提供的新子命令: go tool cover可以查看代码测试覆盖率统计信息:

Go语言回顾:从Go 1.0到Go 1.13

 

图来自 https://blog.golang.org/cover

它还能提供代码覆盖信息:

Go语言回顾:从Go 1.0到Go 1.13

 

图来自 https://blog.golang.org/cover

Go 1.3 – 2014.6

该版本包含了栈管理的一个重要改进。在该版本中,栈内存分配采用连续段(contiguous segment)的分配模式以提升内存分配效率。这将为下一个版本将栈size降到2KB奠定基础。之前的分割栈分配方式(segment stack)存在频繁分配/释放栈段导致栈内存分配性能不稳定(较低)的问题,引入新机制后,分配稳定性和性能都有较大改善。

这里是一个json包的例子,图中显示json包对栈size的敏感度:

Go语言回顾:从Go 1.0到Go 1.13

 

图来自 contiguous stack

使用连续段的栈内存分配管理模式解决了一些程序性能低下的问题。下面是html/template包的性能对stack size的敏感度图:

Go语言回顾:从Go 1.0到Go 1.13

 

更多信息可参见[《How Does the Goroutine Stack Size Evolve?”》(https://medium.com/@blanchon.vincent/go-how-does-the-goroutine-stack-size-evolve-447fc02085e5)]。

这个版本还发布了sync.Pool。这个组件允许我们后面重用结构体,减少内存分配的次数。它也将成为Go生态圈中许多性能提升的源头,比如:标准库中的encoding/json、net/http或是Go社区中的zap等。

关于sync.Pool的更多信息,可以参考文章《Understand the Design of Sync.Pool》。

Go开发组在该版本中对channel进行了优化改善,使其性能获得提升。下面是channel在Go 1.2和Go 1.3版本中的基准测试数据对比:

Go语言回顾:从Go 1.0到Go 1.13

 

Go 1.4 – 2014.12

在该版本中,Go提供了对Android的官方支持。使用golang.org/x/mobile包,gopher们可以使用Go编写简单的Android应用。

同时,之前版本中大量用C语言和汇编语言实现的运行时已经被翻译为Go,一个更为精确的垃圾回收器让堆内存分配减少了10~30%。

和版本自身无关的是,Go工程在本次发布后已经从Mercurial迁移到Git,从Google code迁移到github。

Go还发布了go generate命令,该命令可以通过扫码代码中的//go:generate指示器来生成代码,可以帮助Gopher简化代码生成工作。

更多关于这方面的信息可以参考Go blog和这篇文章《Generating code》。

Go 1.5 – 2015.8

这个新版本推迟了两个月发布,目的是适应Go新的开发发布周期:每年二月和八月进行发布:

Go语言回顾:从Go 1.0到Go 1.13

 

图来自:https://github.com/golang/go/wiki/Go-Release-Cycle

在该版本中,垃圾回收器被全面重构。由于引入并发回收器,回收阶段带来的延迟大幅减少。下面是来自一个生产环境服务器上的延迟数据,我们看到延迟从300ms降到了30ms:

Go语言回顾:从Go 1.0到Go 1.13

 

图片来自 https://blog.golang.org/ismmkeynote

这个版本还发布go tool trace命令,通过该命令我们可以实现执行器的跟踪(trace)。这些跟踪是在test执行、运行时生成的,跟踪信息可以通过浏览器呈现:

Go语言回顾:从Go 1.0到Go 1.13

 

图片来自原始Go Execution Tracer文档

Go 1.6 – 2016.2

这个版本的最显著变化是当使用HTTPS时,将默认支持HTTP/2。

垃圾回收器的延迟在该版本中进一步降低:

Go语言回顾:从Go 1.0到Go 1.13

 

图片来自https://blog.golang.org/ismmkeynote

Go 1.7 – 2016.8

这个版本发布了context包。该包用于处理timeout和取消任务。

更多关于context包的信息,可参考文章:《Context and Cancellation by Propagation》。

编译器工具链的性能得到了较大幅度优化,编译速度更快,二进制文件size更小,有些时候幅度可达20~30%。

Go 1.8 – 2017.2

垃圾回收器的延迟在该版本中进一步改善,延迟时间已经全面降到毫秒级别以下:

Go语言回顾:从Go 1.0到Go 1.13

 

图片来自https://blog.golang.org/ismmkeynote

对延迟的优化还将继续。接下来版本的目标是将延迟降到100微秒左右。

这个版本还大幅提升了defer的性能:

Go语言回顾:从Go 1.0到Go 1.13

 

图片来自 https://medium.com/@blanchon.vincent/go-how-does-defer-statement-work-1a9492689b6e

更多关于defer的信息,可以参考文章How Does Defer statement Work?。

Go 1.9 – 2017.8

该版本引入了alias语法。

type byte = uint8

这里byte是unit8的一个alias。

sync包增加了Map类型,该类型支持并发访问(原生map类型不支持)。

关于map的更多信息,参考文章“Concurrency Access with Maps”。

Go 1.10 – 2018.2

在该版本中,test包引入了一个新的缓存机制,所有通过测试的结果都将被缓存下来。当test没有变化时,重复执行test会节省大量运行test的时间。

first run:
ok /go/src/retro 0.027s
second run:
ok /go/src/retro (cached)

go build命令也维护了一个已构建的包的缓存以加速构建性能。

该版本中垃圾回收器并没有显著性能提升。但是Go team为垃圾回收定义了一个新的SLO(Service-Level Objective):

Go语言回顾:从Go 1.0到Go 1.13

 

图片来自https://blog.golang.org/ismmkeynote

Go 1.11 – 2018.8

Go 1.11引入了一个重要的新功能:Go modules。Go module的引入是为了应对过去几年官方调查问卷结果中Go社区反馈的几个主要挑战:

Go语言回顾:从Go 1.0到Go 1.13

 

图片来自 https://blog.golang.org/survey2018-results

另外一个重要功能是一个试验功能:支持WebAssembly。允许开发人员将Go源码编译成一个兼容四个主流浏览器的二进制格式文件。

Go 1.12 – 2019.2

该版本中,go vet基于analysis包进行了重写,使得go vet更为灵活并支持Go开发人员编写自己的checker。

更多关于analyzer的信息可以参考文章《How to Build Your Own Analyzer》。

Go 1.13 – 2019.9

在该版本中,sync.Pool得到了改善:当垃圾回收时,pool中对象不会被完全清理掉。它引入了一个cache,用于在两次GC之前清理pool中未使用的对象实例。

逃逸分析(escape analysis)被重新实现了,在该版本中,Go得意更少地在堆上分配内存了。下面是新旧逃逸分析的基准测试对比:

Go语言回顾:从Go 1.0到Go 1.13

 

图片来自 https://github.com/golang/go/issues/23109


英文原文链接:https://medium.com/a-journey-with-go/go-retrospective-b9723352e9b0

译文链接:https://tonybai.com/2019/09/07/go-retrospective/

本文译者:tony bai,bigwhite. 版权所有.



Tags:Go语言   点击:()  评论:()
声明:本站部分内容来自互联网,内容观点仅代表作者本人,如有任何版权侵犯请与我们联系,我们将立即删除。
▌相关评论
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表
▌相关推荐
Go 1.13版本在2019.9.3正式发布!国外的Gopher Vincent Blanchon发表了一篇文章《Go: Retrospective》(科学上网阅读),对Go从1.0版本到1.13版本做了简要的回顾,这里是那篇文章的...【详细内容】
2019-09-11   Go语言  点击:(0)  评论:(0)  加入收藏
流程控制是每种编程语言控制逻辑走向和执行次序的重要部分,流程控制可以说是一门语言的“经脉”。Go语言中最常用的流程控制有if和for,而switch和goto主要是为了简化代码、...【详细内容】
2019-09-10   Go语言  点击:(6)  评论:(0)  加入收藏
运算符用于在程序运行时执行数学或逻辑运算。运算符Go 语言内置的运算符有: 算术运算符 关系运算符 逻辑运算符 位运算符 赋值运算符算数运算符 注意: ++(自增)和--(自减)在Go语...【详细内容】
2019-09-09   Go语言  点击:(6)  评论:(0)  加入收藏
go语言标准库中对于字符串的操作很完善,以下简单总结一下字符串的操作一、字符串只能用双引号定义二、go里单引号和双引号不通过,可以使用`` 号来定义原始输出,不会进行转义,...【详细内容】
2019-08-30   Go语言  点击:(9)  评论:(0)  加入收藏
虽然在上篇文章中,我们通过尝试性学习探索了 Go 语言中关于面向对象的相关概念,更确切的说是关于封装的基本概念以及相关实现.但那还远远不够,不能满足于一条路,而是应该尽...【详细内容】
2019-08-28   Go语言  点击:(10)  评论:(0)  加入收藏
go语言用来执行一个系统的命令相对python来说还是有点复杂的,执行命令是一个非常常见的需求,如调用一个系统命令,启一个exe等,这里分为几种情况,之后统一总结一下。 只执行命令,...【详细内容】
2019-08-28   Go语言  点击:(22)  评论:(0)  加入收藏
1 题目描述给定一个链表,移除其自末尾起第N个节点后返回该链表。例子:输入:给定链表1->2->3->4->5,且n=2输出:移除链表末尾起第2个节点4后,链表变为1->2->3->5。题目出处:https://...【详细内容】
2019-08-15   Go语言  点击:(4)  评论:(0)  加入收藏
1 题目描述给定一个仅包含数字的字符串,通过返回所有有效的IP地址组合来还原它。例子:输入:"25525511135"输出:["255.255.11.135", "255.255.111.35"]题目出处:https://leetcode...【详细内容】
2019-08-09   Go语言  点击:(29)  评论:(0)  加入收藏
1 题目描述若一个数列至少有三个元素,且任意相邻两元素的差相等,则该数列为一个等差数列。例如,如下三个数列即为等差数列:1, 3, 5, 7, 97, 7, 7, 73, -1, -5, -9如下数列不是...【详细内容】
2019-08-08   Go语言  点击:(15)  评论:(0)  加入收藏
你好,今天我想分享一下,在 Go 语言中串联 HTTP 处理器。在使用 Go 之前, 我使用 Nodejs + ExpressJS 去编写 HTTP 服务器应用。 这个框架提供了很简单的方法去使用中间件和串...【详细内容】
2019-07-25   Go语言  点击:(17)  评论:(0)  加入收藏
Go语言最吸引人的地方是它内建的并发支持。Go语言并发体系的理论是C.A.R Hoare在1978年提出的通信顺序进程(Communicating Sequential Process,CSP)。CSP有着精确的数学模型,并...【详细内容】
2019-07-23   Go语言  点击:(11)  评论:(0)  加入收藏
首先说一下socket,网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket(百度百科)。图片来源于网络其本质就是就是编程接口(API),对TCP、UDP的封...【详细内容】
2019-07-01   Go语言  点击:(45)  评论:(0)  加入收藏
首先想问大家几个问题,作为程序员,应该会几种编程语言呢?工作中最常用的是哪种呢?还想学新的语言吗?我相信每个人的答案都是不一样的,有人用java,有人用php,有人用c++等等,而且我相信...【详细内容】
2019-05-15   Go语言  点击:(24)  评论:(0)  加入收藏
网络编程中cookie和session是必不可少的,今天就简单说一下go语言对session的实现。图片来源于网络cookie,简而言之就是在本地计算机保存一些用户操作的历史信息(当然包括登录信...【详细内容】
2019-05-08   Go语言  点击:(39)  评论:(0)  加入收藏
推荐资讯
相关文章
栏目更新
栏目热门