go modules 简介

咔叽咔叽_7647 · · 1596 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

大部分内容截取官方文档,官方文档才是最权威的!

go modules 发布已经有一段时间了,之前 gopher china 也推荐用这种方式来开发,准备弃用 glide,虽然也很好用-,-/。为了用 modules,已经把 go 升级到 1.12,这里推荐一个工具 gvm,golang 多版本管理工具,类似 node 的 nvm,挺好用的。为什么要用 modules 呢?最大的好处当然是摆脱了 GOPATH 这个比较反人类的设计,其次官方支持。

基本使用

好了。先来快速过一下 modules 的基本使用,详细信息将在后面部分介绍,先从头开始创建模块的简单示例。

示例

在 GOPATH 路径之外,创建一个目录,

$ mkdir -p /tmp/scratchpad/hello
$ cd /tmp/scratchpad/hello

初始化一个新的 module

$ go mod init github.com/you/hello

go: creating new go.mod: module github.com/you/hello

加上代码逻辑。

$ cat <<EOF > hello.go
package main

import (
    "fmt"
    "rsc.io/quote"
)

func main() {
    fmt.Println(quote.Hello())
}
EOF

编译并且运行。

$ go build 
$ ./hello

Hello, world.

go.mod 文件已更新项目所需的明确版本号的依赖项,其中 v1.5.2 是semver标记:

$ cat go.mod

module github.com/you/hello

require rsc.io/quote v1.5.2
日常工作流程

细心的读者可能发现上面的示例中并没有用到go get

我们典型的日常工作流程是:

  • 根据需要在.go代码中添加 import 语句。
  • 标准命令(如go buildgo test)将根据需要自动添加新的依赖项以满足导入(更新go.mod并下载新的依赖项)。
  • 在需要指定版本时,可以使用go get foo@v1.2.3go get foo@mastergo get foo@e3702bed2或者直接编辑go.mod等命令选择指定的依赖项版本。

简要介绍我们可能使用的其他常用功能:

  • go list -m all - 查看项目构建中所有的直接和间接依赖项的最终版本
  • go list -u -m all - 查看项目构建中所有的直接和间接依赖项的次要版本升级和补丁
  • go get -u or go get -u=patch - 更新所有直接和间接依赖项到最新的次要版本或补丁升级(预发布被忽略)
  • go build ./... or go test ./... - 从模块根目录运行时,用来编译或测试模块中所有的包
  • go mod tidy - 从go.mod中删除不再需要的依赖项,并自动添加操作系统,架构和构建标记的一些组合所需要的依赖项
  • go mod vendor - 一个创建 vendor 目录的可选命令

新的概念

Modules 模块

module 是项目相关 Go 包的一个集合,它们作为一个独立单元将项目所需的依赖包版本化。

module 记录精确的依赖项并创建可重复的编译。

总结仓库,模块和包之间的关系:

  • 仓库包含一个或多个 Go 模块。
  • 每个模块包含一个或多个 Go 包
  • 每个包由一个目录中的一个或多个 Go 源文件组成

module 必须根据semver进行语义化版本,通常采用v(major).(minor).(patch)的形式,例如 v0.1.0,v1.2.3 或 v1.5.0-rc.1。

go.mod

模块由 Go 源文件树定义,并在源文件树的根目录中包含 go.mod 文件。模块源代码可能位于 GOPATH 之外。go.mod 文件有四个指令:modulerequirereplaceexclude

这是一个定义模块github.com/my/thing的示例go.mod文件:

module github.com/my/thing

require (
    github.com/some/dependency v1.2.3
    github.com/another/dependency/v4 v4.0.0
)

模块通过module指令在 go.mod 中声明模块标识,该指令声明模块的路径。模块中所有依赖包的导入路径共享模块路径作为公共前缀。模块路径和 go.mod 所在目录到具体包的目录的相对路径共同决定了包的导入路径。

例如,如果要为仓库github.com/my/repo创建一个模块,该模块包含两个包github.com/my/repo/foogithub.com/my/repo/bar,那么 go.mod 文件中的第一行通常会将模块路径声明为module github.com/my/repo,相应的代码结构:

repo/
├── go.mod
├── bar
│   └── bar.go
└── foo
    └── foo.go

在 Go 源代码中,使用包括模块路径在内的绝对路径导入包。例如,如果模块在其 go.mod 中声明为module example.com/my/module,则可以执行以下操作:

import "example.com/my/module/mypkg"

这将从模块example.com/my/module中导入包mypkg

如何使用 Module

如何安装和激活模块

使用模块的两个安装选项是:

  • Go 版本 1.11+
  • master 分支源码安装toolchain

安装完成后,可以通过以下两种方式之一激活模块:

  • 在$GOPATH/src 之外的目录中调用 go 命令,在当前目录或其任何父目录中使用有效的 go.mod 文件,并且环境变量GO111MODULE未设置(或显式设置为auto
  • 设置环境变量 GO111MODULE=on
如何定义模块

为现有项目创建 go.mod:

  1. 切换到 GOPATH 之外的目录:
$ cd <project path outside $GOPATH/src>         # e.g., cd ~/projects/hello

需要注意的是,在 GOPATH 目录之外无需设置GO111MODULE环境变量来激活模块。

或者,如果你想在 GOPATH 中运行:

$ export GO111MODULE=on                         # manually active module mode
$ cd $GOPATH/src/<project path>                 # e.g., cd $GOPATH/src/you/hello
  1. 初始化模块:
$ go mod init  

此步骤从现有的 dep Gopkg.lock 文件或其他九种支持的依赖文件(类似glide.lock详细戳),为 go.mod 添加 require 语句以匹配现有配置。

go mod init通常能够使用辅助数据(例如 VCS 元数据)来自动确定相应的模块路径,但是如果go mod init表明它不能自动确定模块路径,则你需要以其他方式覆盖 path,你可以提供模块路径作为go mod init的可选参数,例如:

$ go mod init github.com/my/repo
  1. 构建模块。在模块的根目录执行,./...模式匹配当前模块中的所有包。 go build 将根据需要自动添加没有的依赖项或未转换的依赖项
$ go build ./...
  1. 按配置测试模块,以确保它适用于所选版本:
$ go test ./...
  1. (可选)运行模块的测试以及所有直接和间接依赖项的测试以检查兼容性:
$ go test all

有疑问加站长微信联系(非本文作者)

本文来自:简书

感谢作者:咔叽咔叽_7647

查看原文:go modules 简介

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1596 次点击  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传