29

Go1.14 发布了,快来围观新的特性啦 | Go 技术论坛

 4 years ago
source link: https://learnku.com/articles/41949?
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

Go1.14 发布了,快来围观新的特性啦

/ 84 / 0 / 发布于 5个月前

如期而至,Go1.14 发布了,和往常一样,该版本保留了 Go 1 兼容性的承若,这个版本的大部分更新在工具链 、运行时库的性能提升方面,总的来说,还是在已有的基础上不断优化提成,大家期待的泛型还没有到来,下面一块看看新的变化吧,以下变化我本地测试过。

Go 1.14 test 优化#

go test -v 现在将 t.Log 输出流式传输,而不是在所有测试数据结束时输出。

testing 包的 T、B 和 TB 都加上了 CleanUp 方法,主要作用可以用来测试结束后清理资源,如下代码,输出结果是 test cleanup, clear resourcce , 那么问题来了,如果我在方法中再加一个 defer 呢,是 Cleanup 最后执行还是 defer 最后执行

func TestCleanup(t *testing.T) {
   t.Cleanup(func() {
      t.Log("clear resource")
   })
   t.Log("test cleanup")
}

看下面测试代码,我们在 Cleanup 之前和之后都加上 defer 函数,打印结果如下,我们可以看到,Cleanup 还是在 defer 之后,原理暂时不说了,我也没研究。

func TestCleanup(t *testing.T) {
   defer func() { t.Log("defer resource1") }()
   t.Cleanup(func() {
      t.Log("clear resource")
   })
   defer func() { t.Log("defer resource2") }()
   t.Log("test cleanup")
}
test cleanup
defer resource2
defer resource1
clear resource
Go 1.14 defer 优化#

defer 与直接调用延迟函数相比, 此版本提高了大多数使用的性能,从而产生了几乎为零的开销。结果,defer 现在可以在对性能至关重要的代码中使用,而无需担心开销,我们看一下压测报告

//声明一个通道
type channel chan string
//正常关闭
func NoDefer() {
    ch1 := make(channel, 10)
    close(ch1)
}
//采用defer关闭
func Defer() {
    ch2 := make(channel, 10)
    defer close(ch2)
}

Go1.13 的基准测试报告如下

Go1.14发布了,快来围观新的特性啦

Go1.14 的基准测试报告如下

Go1.14发布了,快来围观新的特性啦

关于这一改进,官方给出的回应是:Go1.14 提高了 defer 的大多数用法的性能,几乎 0 开销!defer 已经可以用于对性能要求很高的场景了.

Go1.14 添加了新包 maphash#

包 maphash 提供字节序列的哈希函数。这些哈希函数用于实现哈希表或其他数据结构,这些数据结构需要将任意字符串或字节序列映射到无符号 64 位整数上的统一分布,哈希函数是抗冲突的,但不是加密安全的

func MapHashStudy() {
   b := []byte("foo")
   h1 := new(maphash.Hash)
   h1.Write(b)
   //输出字节数组的hash值
   fmt.Println(h1.Sum64())  //63175979700884496
}
Go1.14 time.Timer 定时器性能得到 “巨幅” 提升#

下图是官方的一个压测数据报告,从基准测试的结果可以看出 Go1.14 time 包中 Ticker 等函数性能都得到了 “巨幅” 提升,数据来源如下,我们可以看到 Ticker 从 5.4ms 提成到了 0.03ms,非常恐怖的

https://github.com/golang/go/commit/6becb033341602f2df9d7c55cc23e64b925bbee2

Go1.14发布了,快来围观新的特性啦
Go1.14 goroutine 支持异步抢占#

Go 语言调度器的性能随着版本迭代表现的越来越优异,GMP 的概念大家应该都知道,不明白了可以百度一下,这里不说了。

在 Go1.1 版本中,调度器还不支持抢占式调度,只能依靠 goroutine 主动让出 CPU 资源,存在非常严重的调度问题。

Go1.12 中编译器在特定时机插入函数,通过函数调用作为入口触发抢占,实现了协作式的抢占式调度。但是这种需要函数调用主动配合的调度方式存在一些边缘情况,就比如说下面的例子:

func main() {
        runtime.GOMAXPROCS(1)  
        go func() {
                for {
                }
        }()
        time.Sleep(time.Millisecond)
        println("OK")
}

上面代码中,其中创建一个 goroutine 并挂起, main goroutine 优先调用了 休眠,此时唯一的 P 会转去执行 for 循环所创建的 goroutine,进而 main goroutine 永远不会再被调度。换一句话说在 Go1.14 之前,上边的代码永远不会输出 OK,因为这种协作式的抢占式调度是不会使一个没有主动放弃执行权、且不参与任何函数调用的 goroutine 被抢占。

Go1.14 实现了基于信号的真抢占式调度解决了上述问题。Go1.14 程序启动时, 会在函数 runtime.sighandler 中注册了 SIGURG 信号的处理函数 runtime.doSigPreempt,在触发垃圾回收的栈扫描时,调用函数挂起 goroutine,并向 M 发送信号,M 收到信号后,会让当前 goroutine 陷入休眠继续执行其他的 goroutine

Go1.14 生态建设#

https://pkg.go.dev 是 go.org 的配套网站,里边有精选用例和其他资源的信息,提供了 godoc.org 之类的 Go 文档,但它使用起来更方便,并提供了有关软件包先前版本的信息,它还可以检测并显示许可证,并具有更好的搜索算法。

Go1.14发布了,快来围观新的特性啦

如上图,是网站的首页,大家可以进去搜索一下,看看有没有新发现。

最后,Go1.14 还有很多改动#
  1. WebAssembly 的变化
  2. reflect 包的变化
  3. go mod 的变化
  4. 很多其他重要的包(math,http 等)的改变

很多变化需要大家去探索,本文列出了其中几个我认为大家必须知道的改变,只是入门,更多原理需要大神们不断探索,当然我也会尽可能的阅读源码研究。

Go1.14发布了,快来围观新的特性啦
本作品采用《CC 协议》,转载必须注明作者和本文链接
那小子阿伟

About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK