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


    如期而至,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提高了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 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 还有很多改动

    1. WebAssembly的变化
    2. reflect包的变化
    3. go mod的变化
    4. 很多其他重要的包(math,http等)的改变

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

    ![](https://img2018.cnblogs.com/blog/706455/201909/706455-20190911210708072-261554801.jpg)

  • 相关阅读:
    VScode网页开发工具
    Java修饰符总结
    C++进阶补充
    C++进阶
    计算机简单开发的基础
    C++动态规划和递归
    C++设计模式
    C++ virtual
    C++-基于STL的演讲比赛流程管理系统
    C++6(5补充)
  • 原文地址:https://www.cnblogs.com/sy270321/p/12376597.html
Copyright © 2020-2023  润新知