0. 前言

  • 最近加入鹅厂学习 k8s,组内使用 Go 1.11 以上的 go modules 管理依赖,因此整理了相关资料
  • 本文严重参考原文:初窥Go module

1. 传统 Golang 包依赖管理

  • Golang 设计深受 Google 主干开发模型影响:

    • 所有开发人员基于主干 trunk/mainline 开发:提交到 trunk 或从 trunk 获取最新的代码(同步到本地 workspace)
    • 版本发布时,建立 Release branch,release branch 实质上就是某一个时刻主干代码的快照
    • release branch 上 的 bug fix 和增强改进代码也通常是先在主干上提交(commit),然后再 cherry-pick 到 release branch 上

  • Golang 中的 go get 的设计深受 Google 内部单一代码仓库(single monorepo)和基于主干(trunk/mainline based)的开发模型的影响:只获取 trunk/mainline 最新版本
  • go get 获取的代码会放在 $GOPATH/src 下面,而 go build 会在 $GOROOT/src 和 $GOPATH/src 下面按照 import path 去搜索 package
  • 由于 go get 获取的都是各个 package repo 的 trunk/mainline 的代码,因此 Go 1.5 之前的 Go compiler 都是基于目标 Go 程序依赖包的 trunk/mainline 代码去编译的
  • 这样的机制带来的问题包括:
    • trunk/mainline 代码时刻变化,不同人不同时刻获取的代码可能不同(即不能实现 reproduceable build)
    • 依赖包的 trunk 演进可能会导致代码无法编译
  • 为了实现 reporduceable build,Go 1.5 引入了 govendor 机制
    • Golang 编译器会优先在 vendor 下搜索依赖的第三方包
    • 开发者将特定版本的依赖包存放在 vendor 下面并提交到代码库
    • 那么所有人理论上都会得到同样的编译结果,从而实现reporduceable build
  • 在Go 1.5 发布后的若干年,Gopher 们把注意力都集中在如何利用 vendor 解决包依赖问题
    • 从手工添加依赖到 vendor
    • 手工更新依赖,到一众包依赖管理工具的诞生:比如: govendor、glide 以及号称准官方工具的 dep
    • 努力地尝试着按照当今主流思路解决着诸如:“钻石型依赖”等难题
  • 正当 Gopher 认为 dep 将顺理成章地升级为 go toolchain 一部分的时候,vgo 横空出世
  • 在原 Go tools 上简单快速地实现 了Go 原生的包依赖管理方案 ,vgo 就是 go modules 的前身

2. go modules 简介

  • 通常我们会在一个仓库中创建一组 package,仓库的路径比如:github.com/bigwhite/gocmpp 会作为 go package 的导入路径(import path)
  • GOPATH 模式下,编译器会根据 package 路径在 $GOPATH/src 或者 vendor 下逐级目录匹配
  • Go 1.8 版本中,如果开发者没有显式设置 $GOPATH,Go 会赋予 GOPATH 一个默认值(在 linux 上为 $HOME/go)
  • Go 1.11 给这样的一组在同一仓库下面的 packages 赋予了一个新的抽象概念:module
  • 并启用一个新的文件 go.mod 记录 module 的元信息
  • 一个仓库对应一个 module 或者多个 module
  • 在 go modules 下,仓库顶层目录下会放置一个 go.mod 文件,每个 go.mod 文件定义了一个 module,而放置 go.mod 文件的目录被称为 module root 目录(通常对应一个仓库的 root 目录,但不是必须的)
  • module root 目录以及其子目录下的所有 packages 均归属于该 module,除了那些自身包含 go.mod 文件的子目录
  • 在 go modules 下,Golang 编译器将不再在 GOPATH 下面以及 vendor 下面搜索目标程序依赖的第三方 packages

3. 尝试使用 go modules

  • 设置环境变量 GO111MODULE:

    • GO111MODULE=off:无模块支持,go 会从 GOPATH 和 vendor 文件夹寻找包
    • GO111MODULE=on:模块支持,go 会忽略 GOPATH 和 vendor 文件夹,只根据 go.mod 下载依赖
    • GO111MODULE=auto:在 $GOPATH/src 外面且根目录有 go.mod 文件时,开启模块支持
  • 在使用模块的时候,GOPATH 是无意义的,不过还是会把下载的依赖储存在 $GOPATH/pkg/mod 中,也会把 go install 的结果放在 $GOPATH/bin
  • 在 ~/test 下创建 hello 目录,然后写入 hello.go(此时不在 $GOPATH 中)
// hello.go
package main import "bitbucket.org/bigwhite/c" func main() {
c.CallC()
}
  • 在 ~/test/hello 下创建 go.mod:

// go.mod
module hello
  • 构建 hello.go:
$ go build hello.go
go: finding bitbucket.org/bigwhite/c v1.3.0
go: downloading bitbucket.org/bigwhite/c v1.3.0
go: extracting bitbucket.org/bigwhite/c v1.3.0
go: finding bitbucket.org/bigwhite/d v1.2.0
go: downloading bitbucket.org/bigwhite/d v1.2.0
go: extracting bitbucket.org/bigwhite/d v1.2.0 $ ./hello.exe
call C: v1.3.0
--> call D:
call D: v1.2.0
--> call D end
  • 查看 go.mod:
$ cat go.mod
// go.mod
module hello go 1.12 require bitbucket.org/bigwhite/c v1.3.0 // indirect
  • indirect 指不是由主 mod 直接引用的包,而是由其他 mod 间接引用的包
  • 如果之后新增了该 mod 的直接引用,会删除上面的间接引用
  • go compiler 将下载的依赖包缓存在 $GOPATH/pkg/mod 下面:
$ pwd
/e/Coding/Golang/go/pkg/mod/cache/download $ ls
bitbucket.org/ github.com/ golang.org/ gopkg.in/ sigs.k8s.io/
cloud.google.com/ go.uber.org/ google.golang.org/ k8s.io/
  • 具体执行:

$ ./hello.exe
call C: v1.3.0
--> call D:
call D: v1.2.0
--> call D end

4. 参考文献

Golang(八)go modules 学习的更多相关文章

  1. go modules 学习

    go modules 学习 tags:golang 安装 只需要golang的版本是1.11及之后的,这个模块就内置好了 环境变量 (1) 配置GoLang的GOROOT (2) 可以不配置GoLan ...

  2. 八、Android学习第七天——XML文件解析方法(转)

    (转自:http://wenku.baidu.com/view/af39b3164431b90d6c85c72f.html) 八.Android学习第七天——XML文件解析方法 XML文件:exten ...

  3. 孤荷凌寒自学python第八十一天学习爬取图片1

    孤荷凌寒自学python第八十一天学习爬取图片1 (完整学习过程屏幕记录视频地址在文末) 通过前面十天的学习,我已经基本了解了通过requests模块来与网站服务器进行交互的方法,也知道了Beauti ...

  4. golang日志框架--logrus学习笔记

    golang日志框架--logrus学习笔记 golang标准库的日志框架非常简单,仅仅提供了print,panic和fatal三个函数,对于更精细的日志级别.日志文件分割以及日志分发等方面并没有提供 ...

  5. go modules学习

    https://github.com/golang/go/wiki/Modules https://tonybai.com/2018/07/15/hello-go-module/ https://ww ...

  6. [goa]golang微服务框架学习--安装使用

      当项目逐渐变大之后,服务增多,开发人员增加,单纯的使用go来写服务会遇到风格不统一,开发效率上的问题. 之前研究go的微服务架构go-kit最让人头疼的就是定义服务之后,还要写很多重复的框架代码, ...

  7. 第八周java学习总结

    学号 20175206 <Java程序设计>第八周学习总结 教材学习内容总结 第十五章:泛型与集合框架 主要内容 泛型 链表 堆栈 散列映射 树集 树映射 重点和难点 重点:泛型和集合的使 ...

  8. golang 关于 interface 的学习整理

    Golang-interface(四 反射) go语言学习-reflect反射理解和简单使用 为什么在Go语言中要慎用interface{} golang将interface{}转换为struct g ...

  9. 20165223《Java程序设计》第八周Java学习总结

    教材学习内容总结 第12章-JAVA多线程机制 要点 Java中的线程 Thread类与线程的创建 线程的常用方法 线程同步 协调同步的线程 线程联合 GUI线程 计时器线程 教材学习中的问题和解决过 ...

随机推荐

  1. 关于如何提高缓存命中率(redis)

    一.缓存命中率的介绍 命中:可以直接通过缓存获取到需要的数据. 不命中:无法直接通过缓存获取到想要的数据,需要再次查询数据库或者执行其它的操作.原因可能是由于缓存中根本不存在,或者缓存已经过期. 通常 ...

  2. 何谓SQLSERVER参数嗅探(转载)

    大家听到“嗅探”这个词应该会觉得跟黑客肯定有关系吧,使用工具嗅探一下参数,然后截获,脱裤o(∩_∩)o .事实上,我觉得大家太敏感了,其实这篇文章跟数据库安全没有什么关系,实际上跟数据库性能调优有关相 ...

  3. C# 实现 奇数偶数排序,奇数在前,偶数在后

    public static void SortByOddAndEven(int []arr) { for (int i = 0; i < arr.Length; i++) { for (int ...

  4. v-model绑定一个对象,组件内部分别负责不同字段的场景实现

    我们知道v-model对于单个property双向数据绑定非常有用,保持父子组件之间的数据传递和同步,但也有很多场景下希望一个组件能够处理多个数据字段,这时就有一些小小技巧了. https://sim ...

  5. MySQL入门——在Windows下安装MySQL

    MySQL入门——在Windows下安装MySQL 摘要:本文主要说明了如何下Windows环境下安装MySQL. 查看电脑上是否安装了MySQL 打开cmd窗口,输入 services.msc 命令 ...

  6. 初识Android App自动化测试框架--Unittest

    1.为什么需要使用框架实现自动化测试 作为测试工程师,可能在代码能力上相比开发工程师要弱一点,所以我们在写脚本的时候就会相对容易的碰到更多的问题,如果有一个成熟的框架供给我们使用的话,可以帮助我们避免 ...

  7. centos7安装jdk1.7(rpm版)

    一.环境 centos7 jdk-7u80-linux-x64.rpm下载:链接:https://pan.baidu.com/s/10UMrxNE1d2ZbDt7kvBM1yQ   提取码:pmov  ...

  8. 浅析Java中线程组(ThreadGroup类)

    Java中使用ThreadGroup类来代表线程组,表示一组线程的集合,可以对一批线程和线程组进行管理.可以把线程归属到某一个线程组中,线程组中可以有线程对象,也可以有线程组,组中还可以有线程,这样的 ...

  9. ASP.NET Core系列:中间件

    1. 概述 ASP.NET Core中的中间件是嵌入到应用管道中用于处理请求和响应的一段代码. 2. 使用 IApplicationBuilder 创建中间件管道 2.1 匿名函数 使用Run, Ma ...

  10. 你所不知的 PHP 断言(assert)

    PHP 中的断言常用于调试,检查一个表达式或语句是否为 FALSE.本文带你重新认识 PHP assert() 函数的神(Qi)通(Yin)广(Ji)大(Qiao). 本文基于 PHP Version ...