Go:管理多个Go版本


原文地址
作为Go编程语言用户,我发现在一个项目中支持运行多个go版本是很有用的。如果你曾经尝试或考虑过这个事情,那就太好了!
在这篇文章中,我将介绍什么时候以及如何启用多个Go版本。最后,我们将讨论为什么这种用法如此强大。
下面开始

我们什么时候需要多个Go版本?

安装了Go意味着您可以运行一个Go命令来构建和测试项目。这只是一个简单的开始,离真正使用可能还存在限制。
一个更灵活的设置是,通过go1.15或go1.16命令,可以在同一个环境中运行多个版本。另一种方法是将终端的PATH环境变量设置为指向特定Go版本的SDK。
在一些情况下,我发现拥有多个版本是有益的:
1、项目之间的不同需求——在多个项目之间切换时,经常需要为每个项目使用不同的Go版本。
2、创建特定的测试环境——在测试向后兼容性或确保bug修复成功时,控制运行时版本是很重要的。
3、保持最新——当测试新特性或包需在最新的Go版本中可用。

条件准备

本指南假设您已经了解如何使用Go构建和运行程序。具体来说,这意味着您已经安装了可用的Go和Git。

  1. Go – https://golang.org/doc/install
  2. Git – https://git-scm.com/
  3. Modules – Using Go Modules

如何使用多个Go版本

我们可以使用go get命令来获取go的各个版本。
运行go get golang.org/dl/go<version>将下载并安装特定版本的Go命令包装器。
通过使用Go包装器,我们可以下载特定版本的Go,并运行该版本的Go工具链。
例如Go v1.16.4

$ go get golang.org/dl/go1.16.4
$ go1.16.4 download

使用go1.16.4包装器,我们可以使用Go v1.16.4进行构建和测试。例如:

$ go1.16.4 mod init hello
go: creating new go.mod: module hello
$ echo 'package main; import "fmt"; func main() { fmt.Println("Hello, World") }' > hello.go
$ go1.16.4 build
$ ./hello
Hello, World

另一个选择是使用我们刚刚下载的版本并设置GOROOT。这会将特定的版本添加到系统路径中:

$ export GOROOT=$(go1.16.4 env GOROOT)
$ export PATH=${GOROOT}/bin;${PATH}

你可以通过上面的GOROOT值删除对应文件夹以卸载特定版本。
还有一个特别版本,叫做gotip,它可以从开发树中获得Go的最新版本:

$ go get golang.org/dl/gotip
$ gotip download

注意,gotip下载并构建当前的开发版本。它还可以接受其他参数——分支名称或更改列表(CL),并使用它来提取特定的Go版本。

在钩子下如何工作

https://go.googlesource.com/dl库保存了这个功能的代码。它包含:
1、每个Go版本有一个小应用程序-例如:go1.16.4/main.go
2、实现Go包装器功能的内部包:internal/version/version. Go
3、生成Go包装器代码的应用程序:internal/genv/main.go
对于每个版本的main.go,go包装类似如下代码:

package main

import "golang.org/dl/internal/version"

func main() {
 version.Run("go1.16.4")
}

正如你所看到的,没多少复杂。只是简单地调用需使用版本的公共代码。
一个打包版本的Run函数,基于命令行参数执行两个主要任务:
1、下载-运行go<version>下载
2、包装go工具链-运行go<version> <anything else>

下载

根据提供的版本、操作系统和平台将从 https://dl.google.com/go中下载Go SDK安装包保存在/home/sdk目录下。
接着,使用sha256验证安装包的完整性,方法是从下载服务器获取checksum文件。最后,它将安装包解压,并创建一个名为unpack -success 的空标记文件。
Gotip版本-当使用gotip下载时,我们只有可用的源代码—最新的或特定的分支/变更列表。

gotip: usage: gotip download [CL number | branch name]

gotip下载将使用git来获取源文件,执行清理,并运行相关的make脚本来构建Go。
与解压特定版本不同,没有标记文件来标记解压成功。相反,gotip将总是尝试获取最新版本并运行构建过程。

包装器

包装器首先验证我们有一个有效的SDK,验证我们在相关的Go文件夹下有一个unpacked-success标记文件。
如果缺少go<verison>将会有错误信息提示相应go版本未下载。运行go<version> download在/home/sdk/go<version>目录下安装。以下摘自internal/version/version.go代码,基于我们想要执行的go版本,格式化要执行的命令。 它使用GOROOT环境变量——设置正确的路径(并将其添加到path中)。

func runGo(root string) {
 gobin := filepath.Join(root, "bin", "go"+exe())
 cmd := exec.Command(gobin, os.Args[1:]...)
 cmd.Stdin = os.Stdin
 cmd.Stdout = os.Stdout
 cmd.Stderr = os.Stderr
 newPath := filepath.Join(root, "bin")
 if p := os.Getenv("PATH"); p != "" {
 newPath += string(filepath.ListSeparator) + p
 }
 cmd.Env = dedupEnv(caseInsensitiveEnv, append(os.Environ(), "GOROOT="+root, "PATH="+newPath))

 handleSignals()

 if err := cmd.Run(); err != nil {
 os.Exit(1)
 }
 os.Exit(0)
}

为每个版本提供一个Go包装器主程序,需要使用一个辅助命令- genv。它接受我们想要构建特定版本的go包装器作为输入。
首先,运行go list -m -json并解析输出:

$ go list -m -json
{
        "Path": "golang.org/dl",
        "Main": true,
        "Dir": "<workspace>/dl",
        "GoMod": "<workspace>/dl/go.mod",
        "GoVersion": "1.11"
}

然后它将Path匹配为golang.org/dl,并使用Dir作为包装器代码的目标目录(' <version>/main.go ')。
最后,它使用可用的Go模板来呈现上面所述的Go包装器代码。

总结

运行多个Go版本是很简单的——它使用了Go工具。并为我们提供了一种以最少的编码访问不同版本的Go sdk的方法。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,752评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,100评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,244评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,099评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,210评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,307评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,346评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,133评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,546评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,849评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,019评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,702评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,331评论 3 319
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,030评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,260评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,871评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,898评论 2 351

推荐阅读更多精彩内容