如何在自己的项目中使用私有 Go 模块

作者选择了 多样性在技术基金作为 写给捐款计划的一部分接受捐款。

介绍

Go的生态系统的一个有益的方面是,大量的模块是开源的,因为它们是开源的,它们可以自由访问,检查,使用和学习,但有时有必要为各种原因创建一个私人Go模块,例如保持企业内部的专有业务逻辑。

在本教程中,您将发布私有 Go 模块,设置身份验证以访问私有模块,并在项目中使用私有 Go 模块。

前提条件

  • Go 版本 1.16 或更高版本已安装. 要设置此功能,请遵循 How To Install Go 为您的操作系统的教程
  • 了解如何分发 Go 模块,您可以在 How To Distribute Go Modules 教程中找到
  • 熟悉 Git,您可以通过下面的 How To Use Git: A Reference Guide 获得。
  • 一个空白的私人 GitHub 存储库,名为 mysecret 为您发布的私人模块。 要开始,请遵循 [GitHub 创建存储库的文档(][INKL3])。(

发行私人模块

与许多编程语言不同,Go将模块从存储库分发,而不是中央包服务器。这种方法的一个好处是,发布私有模块与发布公有模块非常相似.而不是需要完全独立的私有包服务器,Go私有模块通过私有源代码存储库分发。

为了使用私有模块,您需要访问私有 Go 模块. 在本节中,您将创建和发布私有模块,您可以在教程中稍后使用,从另一个 Go 程序访问私有模块。

要创建你的新的私人Go模块,开始克隆私人GitHub存储库,在那里它将生活。作为前提的一部分,你在你的GitHub帐户中创建了一个名为mysecret的私人,空的存储库,这是你将使用的私人模块。这个存储库可以在你的计算机上任何地方克隆,但许多开发人员往往有他们的项目的目录。

创建项目目录并导航到它:

1mkdir projects
2cd projects

项目目录中运行git 克隆,将您的私人mysecret存储库克隆到您的计算机:

1git clone [email protected]:your_github_username/mysecret.git

Git 将确认它已经克隆了您的模块,并可能警告您,您已经克隆了一个空的存储库。

1[secondary_label Output]
2Cloning into 'mysecret'...
3warning: You appear to have cloned an empty repository.

接下来,使用cd进入你克隆的新的mysecret目录,并使用go mod init,以及你的私人存储库的名称,创建一个新的Go模块:

1cd mysecret
2go mod init github.com/your_github_username/mysecret

现在你的模块已经创建了,是时候添加一个功能,你可以从另一个项目中使用. 使用nano或你最喜欢的文本编辑器,打开一个与你的存储库相同的名称的文件,如mysecret.go

1nano mysecret.go

mysecret.go文件中,以与您的存储库相同的名称命名包,然后添加一个SecretProcess函数,在呼叫时打印运行秘密过程!的行:

1[label projects/mysecret/mysecret.go]
2package mysecret
3
4import "fmt"
5
6func SecretProcess() {
7    fmt.Println("Running the secret process!")
8}

现在你已经创建了你的私人模块,你会将其发布到你的私人存储库,以便其他人使用它. 因为你的私人存储库只允许你最初访问它,你可以控制谁可以访问你的私人模块。

由于私有和公共 Go 模块都是源存储库,因此发布私有 Go 模块跟发布公有模块相同的过程。

1git add .
2git commit -m "Initial private module implementation"

您将看到Git的确认,您的初始委托成功,以及包括在委托中的文件的摘要:

1[secondary_label Output]
2[main (root-commit) bda059d] Initial private module implementation
3 2 files changed, 10 insertions(+)
4 create mode 100644 go.mod
5 create mode 100644 mysecret.go

现在剩下的唯一部分是将您的更改移动到您的GitHub存储库。类似于公共模块,使用git push命令发布您的代码:

1git push

然后,Git将推动您的更改,并将其提供给任何有访问您的私人存储库的人:

1git push origin main
2Enumerating objects: 4, done.
3Counting objects: 100% (4/4), done.
4Delta compression using up to 8 threads
5Compressing objects: 100% (3/3), done.
6Writing objects: 100% (4/4), 404 bytes | 404.00 KiB/s, done.
7Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
8To github.com:your_github_username/mysecret.git
9 * [new branch]      main -> main

与公共 Go 模块一样,您还可以将版本添加到您的私人 Go 模块中。

在本节中,您创建了一个具有秘密过程功能的新模块,并将其发布到您的私人秘密GitHub存储库中,使其成为一个私人Go模块,但为了从另一个Go程序访问该模块,您需要配置Go,以便它知道如何访问该模块。

配置 Go 访问私人模块

虽然Go模块通常是从其源代码存储库中分发的,但Go团队还运行了一些 中央Go模块服务以帮助确保模块继续存在,如果发生了什么事发生在原始存储库中。默认情况下,Go 配置用于使用这些服务,但当您尝试下载私人模块时,它们可能会引起问题,因为他们没有访问这些模块。 要告诉Go 某些导入路径是私密的,并且它不应该尝试使用中央Go服务,您可以使用GOPRIVATE环境变量。

为了使用私有模块,您将通过将其设置在GOPRIVATE变量中告知Go将其视为私有的路径。在设置GOPRIVATE变量值时,您可以做出几个选择。 一个选项是将GOPRIVATE设置为github.com

下一个选项是将GOPRIVATE设置为您自己的用户路径,例如github.com/your_github_username。这解决了考虑所有GitHub私有化的问题,但在某个时候,您可能有您创建的公共模块,您希望通过Go模块镜子下载。

最具体的选项将是设置GOPRIVATE,以准确匹配您的模块的路径,例如:github.com/your_github_username/mysecret

1GOPRIVATE=github.com/your_github_username/mysecret,github.com/your_github_username/othersecret

选择你自己最好的选择是衡量你的情况中的优点和缺点的问题。

由于您现在只有一个私人模块,我们将为该值使用完整的存储名称. 若要在当前终端中设置环境变量 `GOPRIVATE=github.com/your_github_username/mysecret',请使用导出命令:

1export GOPRIVATE=github.com/your_github_username/mysecret

如果您想双重检查它是否已设置,您可以使用env命令以及grep来检查GOPRIVATE名称:

1env | grep GOPRIVATE
1[secondary_label Output]
2GOPRIVATE=github.com/your_github_username/mysecret

即使 Go 现在知道您的模块是私有,但使用该模块还不够,如果你试图将您的私有模块进入到另一个模块中,你可能会看到类似的错误:

1go get github.com/your_github_username/mysecret
1[secondary_label Output]
2go get: module github.com/your_github_username/mysecret: git ls-remote -q origin in /Users/your_github_username/go/pkg/mod/cache/vcs/2f8c...b9ea: exit status 128:
3    fatal: could not read Username for 'https://github.com': terminal prompts disabled
4Confirm the import path was entered correctly.
5If this is a private repository, see https://golang.org/doc/faq#git_https for additional information.

这个错误消息说Go试图下载您的模块,但它遇到了一些它仍然无法访问的东西. 由于Git正在被用来下载该模块,它通常会要求您输入您的凭证。

为 HTTPS 提供私人模块凭证

告诉 Git 如何代表您登录的一种方法是.netrc 文件. 位于用户主目录中,.netrc 文件包含各种主机名称以及这些主机的登录凭证。

默认情况下,当 go get 尝试下载一个模块时,它会先尝试使用 HTTPS. 但是,正如上面的例子所示,它无法请求你的用户名和密码。

要在 Linux、MacOS 或 Windows 子系统 for Linux (WSL) 上创建.netrc 文件,请在主目录中打开.netrc 文件,以便您可以编辑它:

1nano ~/.netrc

接下来,在文件中创建一个新的条目。机器值应该是您设置身份证的主机名称,在这种情况下是github.com登录值应该是您的GitHub用户名。

1[label ~/.netrc]
2machine github.com
3login your_github_username
4password your_github_access_token

如果您更愿意,您也可以将整个条目放在文件中的一个行上:

1[label ~/.netrc]
2machine github.com login your_github_username password your_github_access_token

<$>[note] 注: 如果您正在使用 Bitbucket为您的源代码托管,您可能还需要在bitbucket.org之外添加api.bitbucket.org的第二条条目。在过去,Bitbucket提供了多种类型的版本控制托管,所以Go会使用API来检查存储库类型,然后再试图下载它。

1go get bitbucket.org/your_github_username/mysecret: reading https://api.bitbucket.org/2.0/repositories/your_bitbucket_username/protocol?fields=scm: 403 Forbidden
2    server response: Access denied. You must have write or admin access.

如果您在尝试下载私人模块时看到403 Forbidden错误,请双重检查 Go 试图连接的主机名。

现在您的环境已设置为使用 HTTPS 身份验证来下载您的私人模块,尽管 HTTPS 是 Go 和 Git 试图下载模块的默认方式,但您也可以告诉 Git 使用 SSH。

为 SSH 提供私人模块凭证

要使用您的 SSH 密钥作为您的私人 Go 模块的身份验证方法,而不是 HTTPS,Git 提供了名为insteadOf的配置选项。

在 Linux、MacOS 和 WSL 上,这种配置存在于.gitconfig 文件中. 您可能已经熟悉这个文件,因为它也是您的 commit 电子邮件地址和名称配置的地方。

1nano ~/.gitconfig

一旦你打开了文件,编辑它以包括一个 url 部分为 ssh://[email protected]/ 如下示例:

1[label ~/.gitconfig]
2[user]
3    email = [email protected]
4    name = Sammy the Shark
5    
6[url "ssh://[email protected]/"]
7    insteadOf = https://github.com/

用户相关的url部分的顺序并不重要,您也不需要担心如果文件中除了您刚刚添加的url部分以外没有其他东西。

这个新部分告诉 Git 您使用的任何 URL 以 https://github.com/ 开头的 URL 都应该被替换为 ssh://[email protected]/ 代替。 由于 Go 默认使用 HTTPS,这也会影响您的 go get 命令。 例如,使用您的私人模块,这意味着 Go 会将 github.com/your_github_username/mysecret 导入路径转换为 URL 到 https://github.com/your_github_username/mysecret。 当 Git 遇到此 URL 时,它会看到 URL 匹配 https://github.com/ 参照到 insteadOf 的偏头,并将结果的

同样的模式可以用于GitHub以外的域,只要ssh://git@ URL也适用于该主机。

在本节中,您将 Git 配置为使用 SSH 来下载 Go 模块,通过更新您的.gitconfig 文件并添加一个 "url" 部分。

使用私人模块

在之前的部分中,您已配置 Go 以通过 HTTPS、SSH 或两者访问您的私人 Go 模块,现在 Go 可以访问您的私人模块,它可以与您过去可能使用的任何公共模块类似使用。

在用于项目的目录中,例如项目,使用mkdir命令为新项目创建名为myproject的目录:

1mkdir myproject

一旦目录被创建,请使用cd进入目录,并使用go mod init为您的项目初始化一个新的Go模块,基于您的项目的存储URL,例如github.com/your_github_username/myproject

1cd myproject
2go mod init github.com/your_github_username/myproject
1[secondary_label Output]
2go: creating new go.mod: module github.com/your_github_username/myproject

现在,通过打开main.gonano或您最喜欢的文本编辑器来创建您的项目的第一个代码文件:

1nano main.go

在文件中,设置最初的主要函数,您将从以下位置调用您的私人模块:

1[label projects/myproject/main.go]
2package main
3
4import "fmt"
5
6func main() {
7    fmt.Println("My new project!")
8}

要现在运行您的项目并确保一切都正确设置,您可以使用go run命令,并为其提供main.go文件:

1go run main.go
1[secondary_label Output]
2My new project!

接下来,将您的私人模块添加为新项目的依赖性,使用去获取,类似于公共模块:

1go get github.com/your_github_username/mysecret

然后Go工具将下载您的私人模块的代码,并将其添加为依赖,使用与您最近的 commit 哈希和该 commit 的时间相匹配的版本字符串:

1[secondary_label Output]
2go: downloading github.com/your_github_username/mysecret v0.0.0-20210920195630-bda059d63fa2
3go get: added github.com/your_github_username/mysecret v0.0.0-20210920195630-bda059d63fa2

最后,重新打开main.go文件并更新它以在main函数中添加呼叫到您的私人模块的SecretProcess函数。

 1[label projects/myproject/main.go]
 2package main
 3
 4import (
 5    "fmt"
 6
 7    "github.com/your_github_username/mysecret"
 8)
 9
10func main() {
11    fmt.Println("My new project!")
12    mysecret.SecretProcess()
13}

要查看与您的私人模块运行的最终项目,请再次使用go run命令,同时提供main.go文件作为参数:

1go run main.go

您将从原始代码中看到我的新项目!一行,但现在您还将从导入的mysecret模块中看到运行秘密过程!一行:

1[secondary_label Output]
2My new project!
3Running the secret process!

在本节中,您使用go init创建一个新的Go模块来访问您之前发布的私人模块。一旦您创建了该模块,您然后使用go get下载您的私人模块,就像您使用公共Go模块一样。

结论

在本教程中,您创建并发布了私有 Go 模块. 您还设置了 HTTPS 和 SSH 身份验证以访问您的私有 Go 模块. 最后,您在新项目中使用了私有 Go 模块。

有关 Go 模块的更多信息,Go 项目有 一系列博客帖子详细介绍 Go 工具如何与模块互动和理解。

除了GOPRIVATE环境变量外,在使用私人 Go 模块时还可使用更多变量,这些变量可以在 Go Modules ReferencePrivate Modules部分中详述。

如果您有兴趣更详细地探索.netrc 文件,则 GNU 在.netrc 上的网站(https://www.gnu.org/software/inetutils/manual/html_node/The-_002enetrc-file.html)包含所有可用的关键字列表。

本教程也是 DigitalOcean How to Code in Go系列的一部分,该系列涵盖了许多 Go 主题,从首次安装 Go 到如何使用语言本身。

Published At
Categories with 技术
Tagged with
comments powered by Disqus