标签 RussCox 下的文章

一文告诉你如何抢先体验Go泛型

img{512x368}

本文首发于我主持的“Gopher部落”知识星球,欢迎大家加入星球,一起学习Go语言!年底前8.8折优惠,不要错过哦!

2020年11月22日,Go核心开发团队技术负责人Russ Coxgolang-dev论坛上确认了Go泛型将在Go 1.18落地(2022.2):

img{512x368}

这对于那些迫切期盼go加入泛型的gopher来说无疑是一个重大利好消息!不过,泛型是把双刃剑!泛型的加入势必会让Go语言的复杂性大幅提升。我很是担心Go加入泛型后会像C++模板那样被“滥用”而形成很多奇技淫巧,这显然不是Go项目组想看到的。因此他们现在在宣传泛型时都是比较谨慎的。Robert GriesemerGopherCon 2020大会上演讲“Typing [Generic] Go”中明确给出了Go泛型的使用时机:

  • 可增强静态类型安全性的时候
  • 可以更高效的使用内存的时候
  • 可以(显著的)提升性能的时候

虽然这不能完全避免滥用,但至少表明了Go团队对泛型使用的态度。“能力越大,责任越大”,大家在使用泛型时务必三思而后行

现在,Go泛型已经处于“箭在弦上不得不发”的状态,作为Gopher,我们能做的就是拥抱它!

离Go 1.18发布还有一年多的时间,对于极其渴望支持泛型的gopher来说,这个时间有点长!好在Go项目组已经提供了一些抢先体验Go泛型语法的方法,这里我们就来全面介绍一下,小伙伴们可以根据自己的情况任选一种抢先体验Go泛型!

1. Go泛型在线playground

2020.6月末,Ian Lance Taylor和Robert Griesemer在Go官方博客发表了文章《The Next Step for Generics》,介绍了Go泛型工作的最新进展。同时,Go团队还推出了可以在线试验Go泛型语法的playground:https://go2goplay.golang.org:

img{512x368}

通过该在线playground,我们可以体验最新的Go泛型语法并查看编译和运行结果。

在线playground的好处就在于可以随时随地访问和体验,体验设备也不局限于计算机,甚至可以使用手机/平板终端。不过该playground在国内访问不畅,并且体验仅局限于单文件的形式,对于复杂一些的项目无法支持。

2. 基于源码编译出go2go工具

Go项目在dev.go2go分支上加入了Go泛型语法的实现,我们可以在本地基于Go项目源码构建出可以用于体验Go泛型的go2go工具。

要想构建go2go工具,我们首先就需要下载Go项目源码。但截至目前,Go项目仓库github.com/golang/go有45000多次提交,在国内以20k/s的速度clone这个仓库那是相当耗时费力,还不一定有好结果(经常断连,一断连,就要重新来过)。当然如果你有高速vpn则另当别论了。这里介绍一个下载github上Go项目源码的过渡方法:利用gitee(码云)建立Go仓库镜像库,然后从码云以2M/s速度下载。步骤如下:

  • 在gitee上建立一个公共仓库,比如:gitee.com/bigwhite/go,在建立仓库时选择“导入现有库”,填入现有库的地址:https:///github.com/golang.go.git,之后,强大的“码云”就会帮助我们快速同步了。

  • 之后我们就可以从码云clone这个仓库:gitee.com/bigwhite/go,2M/s的速度,一分钟内就完成clone。并且码云支持强制从源仓库github.com/golang/go同步最新更新到镜像仓库,十分方便。

$git clone https://gitee.com/bigwhite/go.git

既然我已经在码云建立的go仓库的镜像,各位小伙伴儿们就可以直接clone我的公共库(https://gitee.com/bigwhite/go)来获取go仓库源码了。

接下来,我们来构建go2go工具,主要步骤如下(当前环境为ubuntu,并已安装的go的版本为go 1.15.4 linux/amd64):

  • 切换到dev.go2go分支
// 进入下载后的go仓库源码目录(我这里为~/.bin/go)
$git checkout dev.go2go
Branch 'dev.go2go' set up to track remote branch 'dev.go2go' from 'origin'.
Switched to a new branch 'dev.go2go'

注:ubuntu需安装build-essential(apt-get install build-essential),否则在go源码编译过程可能会出现“fatal error: stdlib.h: No such file or directory”的错误。

  • 编译dev.go2go分支源码

Go源码编译是“一键式”的,并且速度非常快!进入到Go项目源码下的src目录(cd ~/.bin/go/src),执行下面命令:

$./all.bash 

Building Go cmd/dist using /root/.bin/go1.15.4. (go1.15.4 linux/amd64)
Building Go toolchain1 using /root/.bin/go1.15.4.
Building Go bootstrap cmd/go (go_bootstrap) using Go toolchain1.
Building Go toolchain2 using go_bootstrap and Go toolchain1.
Building Go toolchain3 using go_bootstrap and Go toolchain2.
Building packages and commands for linux/amd64.
... ...
ALL TESTS PASSED
---
Installed Go for linux/amd64 in /root/.bin/go
Installed commands in /root/.bin/go/bin
*** You need to add /root/.bin/go/bin to your PATH.

构建后的可执行文件go与gofmt被放在了bin目录下(~/go/bin),为方便使用,我们最好将其所在路径配置到PATH环境变量中。。

  • 验证构建结果
$go version
go version devel +440f144a10 Tue Nov 24 01:29:01 2020 +0000 linux/amd64

如果看到上面结果,说明构建是ok的。

接下来,我们就来使用构建出的go工具体验一下编译运行一个使用泛型语法编写的源文件sort.go2

// sort.go2

package main

import (
    "fmt"
    "sort"
)

type Lang struct {
    Name string
    Rank int
}

type sliceFn[T any] struct {
    s   []T
    cmp func(T, T) bool
}

func (s sliceFn[T]) Len() int           { return len(s.s) }
func (s sliceFn[T]) Less(i, j int) bool { return s.cmp(s.s[i], s.s[j]) }
func (s sliceFn[T]) Swap(i, j int)      { s.s[i], s.s[j] = s.s[j], s.s[i] }

func SliceFn[T any](s []T, cmp func(T, T) bool) {
    sort.Sort(sliceFn[T]{s, cmp})
}

func main() {
    langs := []Lang{
        {"rust", 2},
        {"go", 1},
        {"swift", 3},
    }

    SliceFn(langs, func(p1, p2 Lang) bool { return p1.Rank < p2.Rank })
    fmt.Println(langs) // [{go 1} {rust 2} {swift 3}]
}

go2go是以go tool的一个子命令形式存在的,它支持编译和运行以.go2为后缀的Go源文件,如果让它编译和运行.go文件,它会报如下错误:

$go tool go2go run sort.go
Go file sort.go was not created by go2go

编译运行上面的sort.go2的命令和结果如下:

$go tool go2go run sort.go2
[{go 1} {rust 2} {swift 3}]

有小伙伴可能会说,这个例子也是单一源文件,太简单!那我们接下来就整一个稍复杂些的。go2go这个子命令自带了一些复杂的Go泛型包,这些包的源码被放在了Go仓库源码的src/cmd/go2go/testdata下面:

$tree -LF 2 go2path
go2path
└── src/
    ├── alg/
    ├── chans/
    ├── constraints/
    ├── graph/
    ├── gsort/
    ├── list/
    ├── maps/
    ├── metrics/
    ├── orderedmap/
    ├── sets/
    └── slices/

go2go目前仅支持gopath mode,还不支持module-ware mode。go2go支持专用的GO2PATH环境变量用于指示GOPATH路径,也可以用传统的GOPATH环境变量。为了使用go2go自带的那些样例源码包,我们需要将GOPATH或GO2PATH设置为\$GOROOT/src/cmd/go2go/testdata/go2path。我们在go2path路径下建立我们的样例repo:

$tree -LF 5 go2path
go2path
└── src/
    │   ... ...
    ├── github.com/
    │   └── bigwhite/
    │       └── gsort-demo/
    │           └── demo.go2
    │   ... ...
    └── slices/
        ├── slices.go2
        └── slices_test.go2

// demo.go2
package main

import (
    "fmt"
    "gsort"
)

type Lang struct {
    Name string
    Rank int
}

func main() {
    langs := []Lang{
        {"rust", 2},
        {"go", 1},
        {"swift", 3},
    }

    gsort.SliceFn(langs, func(p1, p2 Lang) bool { return p1.Rank < p2.Rank })
    fmt.Println(langs)
}

我们可以用两种方法运行demo.go2:

// 设置GO2PATH:

~/.bin/go/src/cmd/go2go/testdata/go2path/src/github.com/bigwhite/gsort-demo$ GO2PATH=$GOROOT/src/cmd/go2go/testdata/go2path go tool go2go run demo.go2
[{go 1} {rust 2} {swift 3}]

或

// 设置GOPATH和关闭GO111MODULE:

~/.bin/go/src/cmd/go2go/testdata/go2path/src/github.com/bigwhite/gsort-demo$ GOPATH=$GOROOT/src/cmd/go2go/testdata/go2path GO111MODULE=off go tool go2go run demo.go2
[{go 1} {rust 2} {swift 3}]

通过源码构建go2go工具的方法是体验Go泛型最基本的方法,我们还可以定期更新Go项目源码以体验泛型草案的最新变化。我们还可以通过go doc cmd/go2go来查看go2go命令的文档。

3. 使用go2go的docker容器

如果觉得使用源码构建本地可用的go2go工具依然“门槛高”或者繁琐,那么可以利用一些gopher已经上传的现成的docker容器来构建使用了泛型语法的*.go2文件。这里使用的是levonet/golang:go2go

$docker pull levonet/golang:go2go
  • 使用go2go容器编译运行单个*.go2文件

我们还以上面那个sort.go2为例,该文件可以放在任意目录下,然后我们在该文件所在目录下执行下面命令即可编译运行它:

$ docker run --rm -v "$PWD":/go/src/myapp -w /go/src/myapp levonet/golang:go2go go tool go2go run sort.go2
[{go 1} {rust 2} {swift 3}]

这句docker run命令的含义是:将宿主机当前工作目录(即sort.go2所在目录)挂载到容器中的/go/src/myapp下面,并将/go/src/myapp作为当前工作目录,执行go tool go2go run sort.go2

对于复杂的如上面的github.com/bigwhite/gsort-demo的例子,通过docker容器一样可以编译,只不过命令复杂一些:

~/temp/github.com $docker run --rm -v "$PWD":/usr/local/lib/go/src/cmd/go2go/testdata/go2path/src/github.com -w /usr/local/lib/go/src/cmd/go2go/testdata/go2path/src/github.com/bigwhite/gsort-demo -e GO2PATH="/usr/local/lib/go/src/cmd/go2go/testdata/go2path" levonet/golang:go2go go tool go2go run demo.go2
[{go 1} {rust 2} {swift 3}]

我们将github.com目录放在任意目录下,比如:~/temp,然后将当前目录挂载到容器的/usr/local/lib/go/src/cmd/go2go/testdata/go2path/src/github.com目录下,设定工作目录为/usr/local/lib/go/src/cmd/go2go/testdata/go2path/src/github.com/bigwhite/gsort-demo,然后为容器新增以环境变量GO2PATH,这样我们就可以编译运行demo.go2了。

注1:容器中的GOROOT为/usr/local/lib/go

4. 使用Goland体验Go泛型

著名Go语言IDE产品goland也宣布支持体验最新的Go泛型语法,由于笔者很少使用图形化的IDE,因此各位小伙伴可自行通过这篇博客https://blog.jetbrains.com/go/2020/11/24/experimenting-with-go-type-parameters-generics-in-goland/来了解具体情况。

5. 参考资料

  • levonet/golang – https://hub.docker.com/r/levonet/golang
  • dev.go2go branch – https://go.googlesource.com/go/+/refs/heads/dev.go2go/README.go2go.md

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

我的Go技术专栏:“改善Go语⾔编程质量的50个有效实践”上线了,欢迎大家订阅学习!

img{512x368}

我的网课“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}

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

Go,11周年

img{512x368}

本文翻译自Go官方博客文章《Eleven Years of Go》,原作者:Russ Cox

今天,我们一起庆祝Go语言正式开业发布11周年。去年的“Go turning 10”周年庆典聚会似乎已成为久远的回忆。这是艰难的一年,但我们一直保持了Go开发的步伐,并积累了很多亮点。

img{512x368}

在去年11月,我们在庆祝Go 10周年后不久就发布和上线了go.dev和pkg.go.dev站点。

今年2月,Go 1.14版本提供了第一个正式的“生产就绪”的go module实现,并进行了许多性能改进,包括更快的defer真正抢占式的goroutine调度,以减少调度和垃圾收集延迟。

在今年三月初,我们推出了新版protobuf APIgoogle.golang.org/protobuf,大幅改善了对protobuf reflection和自定义消息的支持。

当新冠疫情大流行发生时,我们决定在春季暂停所有公开发布或活动,因为大家都知道所有人的注意力都聚焦在其他地方。但是我们一直在努力,我们的团队中的一个成员加入了Apple/Google发起的“privacy-preserving exposure notifications”项目,以支持全球范围内的联系人追踪工作。5月,该小组启动了用Go编写的 reference backend server

我们继续改进gopls,这让许多编辑器受益并都启用了高级Go-aware支持。六月份,VSCode Go扩展正式加入Go项目,现在由从事gopls的同一位开发人员维护。

同样在6月,由于Go社区的反馈意见,我们还将pkg.go.dev背后的代码开源,并将其作为Go项目的一部分。

6月下旬,我们 发布了有关Go generics的最新设计草案,以及原型工具和一个支持go generics实验语法的playground

7月,我们发布并讨论了三个新的有关Go未来演化的设计草案:go:build文件系统接口构建时文件嵌入。(我们将在2021年看到所有新特性)

8月,Go 1.15版本发布!该版本以优化和bug修复为主,没有提供太多新功能。其最重要的部分是开始重写链接器,这使它在进行大型项目构建时,平均运行速度提高了20%,平均使用的内存减少了30%。

上个月,我们发起了年度Go用户调查。分析结果后,我们会将结果发布到博客上。

Go社区已经与其他所有人一起适应了“虚拟优先”的原则,今年我们看到了许多虚拟聚会和十多个虚拟Go会议。上周,Go团队在Google Open Source Live中举办了“Go Day”活动

前进

我们也对Go语言在其第12年即将发生的事情感到非常兴奋。近期,Go团队成员将参加GopherCon 2020并做以下展示和分享。请打开您的日历,做好提醒标记!

  • 11月11日上午10:00,Robert Griesemer的演讲“Typing [Generic] Go”;在10:30 AM进行Q&A。
  • 11月11日中午12:00,现场播放Go时间播客的实况录像:“What to Expect When You’re NOT Expecting”,该集播客由包括Hana Kim组成的专家调试小组主持。
  • Michael Knyszek在11月11日下午1:00发表演讲“Evolving the Go Memory Manager’s RAM and CPU Efficiency” ;在下午1:50进行Q&A。
  • Dan Scales在11月11日下午5:10发表演讲“Implementing Faster Defers”; 在下午5:40进行Q&A。
  • 11月12日下午3点,与朱莉·邱(Julie Qiu),丽贝卡·史翠宝(Rebecca Stambler),拉斯·考克斯(Russ Cox),萨默·阿杰曼尼(Sameer Ajmani)和范·里珀(Van Riper)一起的现场问答环节“ Go Team-Ask Me Anything” 。
  • 奥斯汀·克莱门茨(Austin Clements)在11月12日下午4:45发表演讲“Pardon the Interruption: Loop Preemption in Go 1.14” ; 在下午5:15进行Q&A。
  • 乔纳森·阿姆斯特丹(Jonathan Amsterdam)在11月13日下午1:00发表的演讲:“Working with Errors” ; 在下午1:50进行Q&A。
  • 卡门·安多(Carmen Andoh)11月13日下午5:55发表的演讲“Crossing the Chasm for Go: Two Million Users and Growing” 。

Go发布计划

2021年2月,Go 1.16版本将发布,该版本将包括新的文件系统接口构建时文件嵌入。它将完成链接器的重写,从而带来更多的性能改进。它将包括对新的Apple Silicon(GOARCH=arm64)Mac的支持。

2021年8月,Go 1.17版本无疑会带来更多功能和改进,尽管远远不够,确切的细节仍然悬而未决。它将包括一个针对x86-64新的基于寄存器的调用约定(不破坏现有程序集!),这将使程序整体更快。(对其他体系结构的支持将在以后的版本中发布。)新的//go:build行肯定会包含一个不错的功能,肯定比当前// +build更不容易出错。我们希望明年可以进行Beta测试的另一个备受期待的功能是对go test命令中的模糊测试(fuzz test)的支持

有关Go module

明年,我们将继续致力于开发对Go module的支持,并将其很好地集成到整个Go生态系统中。Go 1.16将包括我们迄今为止最流畅的Go module体验。我们最近的一项调查的初步结果是,现在有96%的用户已采用Go模块(高于一年前的90%)。

我们还将最终终止对基于GOPATH的开发的支持:使用标准库以外的依赖项的任何程序都将需要一个go.mod。(如果您尚未切换到go module,请参阅GOPATH Wiki页面以获取有关从GOPATH到go module的最后一步的详细信息。)

从一开始,Go module的目标就是“将软件包版本的概念添加到Go开发人员和我们的工具的常用词汇中”,从而为整个Go生态系统中的module和版本提供深度支持。整个生态系统对包版本的广泛理解使得go module镜像、chechsum数据库和module index成为可能。在明年,我们将看到更多module支持被添加到更多的工具和系统中。例如,我们计划研究新的工具,以帮助模块作者发布新版本(go release),并帮助module使用者摆脱过时的API并完成迁移(新的go fix)。

一个更为有说服力的例子是,我们创建了gopls来减少编辑器为支持Go而依赖许多外部工具的情况:将依赖一堆不支持go module的工具转变为只依赖一个支持module的工具。明年,我们将准备让VSCode Go扩展默认使用gopls,以提供出色的、现成的module体验,并将发布gopls 1.0。当然,gopls最大的优势之一是它与编辑器无关:任何支持语言服务器协议的编辑器都可以使用它。

版本信息的另一个重要用途是跟踪构建中的任何程序包是否具有已知漏洞。明年,我们计划开发一个已知漏洞的数据库以及基于该数据库进行漏洞检查的工具程序。

Go软件包发现站点pkg.go.dev是Go module启用的版本感知系统的另一个示例。我们一直致力于正确实现核心功能和用户体验,包括今天重新设计后的pkg.go.dev的上线。明年,我们将godoc.org统一为pkg.go.dev。我们还将扩展展示每个软件包的版本时间线,显示每个版本的重要更改,已知漏洞等,以实现你进行依赖添加决策时所需的所有信息。

我们很高兴看到从GOPATH到Go模块的旅程即将完成,以及Go模块正在启用的所有出色的依赖关系感知工具。

有关Go generics

每个人心中的下一个功能特性当然是泛型。如上所述,我们于今年6月发布了有关泛型最新设计草案。从那时起,我们一直在做细节上的完善,并将注意力转移到了实现可生产版本的细节上。我们将在2021年的整个过程中继续努力,以期在年底之前为人们提供一些试用的目标,也许它是Go 1.18 beta的一部分。

感谢大家

Go不仅限于我们这些Google Go团队的成员。我们要感谢与我们一起开发Go项目和工具的贡献者。除此之外,Go之所以成功,是因为所有在Go蓬勃发展的生态系统中工作并为之贡献的人们。Go之外的世界度过了艰难的一年。非常感谢您抽出宝贵的时间加入我们,并帮助Go取得成功。谢谢。我们希望大家都安全,并祝您一切顺利。


我的Go技术专栏:“改善Go语⾔编程质量的50个有效实践”上线了,欢迎大家订阅学习!

img{512x368}

我的网课“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}

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

如发现本站页面被黑,比如:挂载广告、挖矿等恶意代码,请朋友们及时联系我。十分感谢! Go语言第一课 Go语言精进之路1 Go语言精进之路2 Go语言编程指南
商务合作请联系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